package com.panfeng.xcloud.scheduler.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binance.client.model.enums.CandlestickInterval;
import com.panfeng.xcloud.boss.provider.dto.request.PinBarCandlerStickDetailDTO;
import com.panfeng.xcloud.boss.provider.dto.request.QuantBotDetailDTO;
import com.panfeng.xcloud.common.core.candle.Entry;
import com.panfeng.xcloud.common.core.candle.MyCandleEntry;
import com.panfeng.xcloud.common.core.enums.MovingAverageIndexEnum;
import com.panfeng.xcloud.common.core.enums.MovingAveragePeriodEnum;
import com.panfeng.xcloud.common.core.enums.UserBotStatusTypeEnum;
import com.panfeng.xcloud.common.core.utils.FinanceIndicatorsUtil;
import com.panfeng.xcloud.common.core.utils.KeyContactUtil;
import com.panfeng.xcloud.dao.assets.entity.ProfitAndFeeDetail;
import com.panfeng.xcloud.dao.assets.entity.UserBot;
import com.panfeng.xcloud.dao.assets.entity.UserWalletInfo;
import com.panfeng.xcloud.scheduler.constants.SystemParamContants;
import com.panfeng.xcloud.scheduler.dao.mapper.ProfitAndFeeDetailMapperExt;
import com.panfeng.xcloud.scheduler.dao.mapper.UserBotMapperExt;
import com.panfeng.xcloud.scheduler.dao.mapper.UserWalletInfoMapperExt;
import com.panfeng.xcloud.scheduler.service.ICalculatePriceService;
import com.panfeng.xcloud.scheduler.service.IFeignService;
import com.panfeng.xcloud.scheduler.service.ITechniqueSymbolService;
import groovy.util.logging.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.ta4j.core.*;
import org.ta4j.core.indicators.*;
import org.ta4j.core.indicators.adx.ADXIndicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;
import org.ta4j.core.num.Num;
import org.ta4j.core.num.PrecisionNum;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 风险控制类
 */
@Slf4j
@Service
public class TechniqueSymbolServiceImpl implements ITechniqueSymbolService {

    @Autowired
    private IFeignService feignService;

    @Autowired
    private ICalculatePriceService iCalculatePriceService;

    @Autowired
    private ProfitAndFeeDetailMapperExt profitAndFeeDetailMapperExt;

    @Autowired
    private UserWalletInfoMapperExt userWalletInfoMapperExt;

    @Autowired
    private UserBotMapperExt userBotMapperExt;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static Logger log = LoggerFactory.getLogger(TechniqueSymbolServiceImpl.class);


    //---------------------------------------------------MA均线多头空头判断-------------------------------------------------

    /**
     * ma均线多头排列开多判断
     */
    @Override
    public Boolean maBuyRange_Open(float[] ma_Low, float[] ma_Mid, float[] ma_High) {
        float ma3_Low = ma_Low[0];
        float ma5_Low = ma_Low[1];
        float ma10_Low = ma_Low[2];
        float ma20_Low = ma_Low[3];

        float ma3_last_Low = ma_Low[4];
        float ma5_last_Low = ma_Low[5];
        float ma10_last_Low = ma_Low[6];
        float ma20_last_Low = ma_Low[7];

        float ma3_last2_Low = ma_Low[8];
        float ma5_last2_Low = ma_Low[9];
        float ma10_last2_Low = ma_Low[10];
        float ma20_last2_Low = ma_Low[11];

        float ma3_Mid = ma_Mid[0];
        float ma5_Mid = ma_Mid[1];
        float ma10_Mid = ma_Mid[2];
        float ma20_Mid = ma_Mid[3];

        float ma3_last_Mid = ma_Mid[4];
        float ma5_last_Mid = ma_Mid[5];
        float ma10_last_Mid = ma_Mid[6];
        float ma20_last_Mid = ma_Mid[7];

        float ma3_last2_Mid = ma_Mid[8];
        float ma5_last2_Mid = ma_Mid[9];
        float ma10_last2_Mid = ma_Mid[10];
        float ma20_last2_Mid = ma_Mid[11];

        float ma3_High = ma_High[0];
        float ma5_High = ma_High[1];
        float ma10_High = ma_High[2];
        float ma20_High = ma_High[3];

        float ma3_last_High = ma_High[4];
        float ma5_last_High = ma_High[5];
        float ma10_last_High = ma_High[6];
        float ma20_last_High = ma_High[7];

        float ma3_last2_High = ma_High[8];
        float ma5_last2_High = ma_High[9];
        float ma10_last2_High = ma_High[10];
        float ma20_last2_High = ma_High[11];

        return (ma3_last_Low >= ma5_last_Low)
                && (ma3_Low > ma3_last_Low)
                && (ma3_last_Low > ma3_last2_Low)

                && (ma3_last_High >= ma5_last_High)
                && (ma3_High > ma3_last_High)
                && (ma3_last_High > ma3_last2_High);
    }

    /**
     * ma均线空头排列开空判断
     */
    @Override
    public Boolean maSellRange_Open(float[] ma_Low, float[] ma_Mid, float[] ma_High) {
        float ma3_Low = ma_Low[0];
        float ma5_Low = ma_Low[1];
        float ma10_Low = ma_Low[2];
        float ma20_Low = ma_Low[3];

        float ma3_last_Low = ma_Low[4];
        float ma5_last_Low = ma_Low[5];
        float ma10_last_Low = ma_Low[6];
        float ma20_last_Low = ma_Low[7];

        float ma3_last2_Low = ma_Low[8];
        float ma5_last2_Low = ma_Low[9];
        float ma10_last2_Low = ma_Low[10];
        float ma20_last2_Low = ma_Low[11];

        float ma3_Mid = ma_Mid[0];
        float ma5_Mid = ma_Mid[1];
        float ma10_Mid = ma_Mid[2];
        float ma20_Mid = ma_Mid[3];

        float ma3_last_Mid = ma_Mid[4];
        float ma5_last_Mid = ma_Mid[5];
        float ma10_last_Mid = ma_Mid[6];
        float ma20_last_Mid = ma_Mid[7];

        float ma3_last2_Mid = ma_Mid[8];
        float ma5_last2_Mid = ma_Mid[9];
        float ma10_last2_Mid = ma_Mid[10];
        float ma20_last2_Mid = ma_Mid[11];

        float ma3_High = ma_High[0];
        float ma5_High = ma_High[1];
        float ma10_High = ma_High[2];
        float ma20_High = ma_High[3];

        float ma3_last_High = ma_High[4];
        float ma5_last_High = ma_High[5];
        float ma10_last_High = ma_High[6];
        float ma20_last_High = ma_High[7];

        float ma3_last2_High = ma_High[8];
        float ma5_last2_High = ma_High[9];
        float ma10_last2_High = ma_High[10];
        float ma20_last2_High = ma_High[11];

        return (ma3_last_Low <= ma5_last_Low)
                && (ma3_Low < ma3_last_Low)
                && (ma3_last_Low < ma3_last2_Low)

                && (ma3_last_High <= ma5_last_High)
                && (ma3_High < ma3_last_High)
                && (ma3_last_High < ma3_last2_High);
    }

    /**
     * ma均线空头排列平多判断
     */
    @Override
    public Boolean maBuyRange_Close(float[] ma_High) {
        float ma3_High = ma_High[0];
        float ma5_High = ma_High[1];
        float ma10_High = ma_High[2];
        float ma20_High = ma_High[3];

        float ma3_last_High = ma_High[4];
        float ma5_last_High = ma_High[5];
        float ma10_last_High = ma_High[6];
        float ma20_last_High = ma_High[7];

        float ma3_last2_High = ma_High[8];
        float ma5_last2_High = ma_High[9];
        float ma10_last2_High = ma_High[10];
        float ma20_last2_High = ma_High[11];

        return ma3_last_High <= ma5_last_High;
    }

    /**
     * ma均线多头排列平空判断
     */
    @Override
    public Boolean maSellRange_Close(float[] ma_High) {
        float ma3_High = ma_High[0];
        float ma5_High = ma_High[1];
        float ma10_High = ma_High[2];
        float ma20_High = ma_High[3];

        float ma3_last_High = ma_High[4];
        float ma5_last_High = ma_High[5];
        float ma10_last_High = ma_High[6];
        float ma20_last_High = ma_High[7];

        float ma3_last2_High = ma_High[8];
        float ma5_last2_High = ma_High[9];
        float ma10_last2_High = ma_High[10];
        float ma20_last2_High = ma_High[11];

        return ma3_last_High >= ma5_last_High;
    }

    //----------------------------------------------------------------------------------------------------------------------

    //---------------------------------------------------MA均线斜率判断-------------------------------------------------

    /**
     * ma均线斜率开多判断
     */
    @Override
    public Boolean maBuySlope_Open(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO, BigDecimal minDegree,
                                   BigDecimal maxDegree, MovingAveragePeriodEnum maPeriod,
                                   MovingAverageIndexEnum index1, MovingAverageIndexEnum index2) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 26);

        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        float maChoose1 = ma[index1.code];
        float maChoose2 = ma[index2.code];

        //指定级别周期
        BigDecimal degree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose1), new BigDecimal(maChoose2));

        //三个周期级别都满足斜率要求才能开多
        return (degree.compareTo(minDegree) > 0)
                &&
                (degree.compareTo(maxDegree) < 0);
    }

    /**
     * 开多两ma均线大小判断
     */
    @Override
    public Boolean twoMaBuySlopeJudge_Open(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO,
                                           BigDecimal minDegree, BigDecimal maxDegree, MovingAveragePeriodEnum maPeriod,
                                           MovingAverageIndexEnum index1, MovingAverageIndexEnum index2,
                                           MovingAverageIndexEnum index3, MovingAverageIndexEnum index4) throws Exception {

        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 26);

        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        float maChoose1 = ma[index1.code];
        float maChoose2 = ma[index2.code];

        BigDecimal degree1 = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose1), new BigDecimal(maChoose2));

        if ((degree1.compareTo(minDegree) > 0) && (degree1.compareTo(maxDegree) < 0)) {
            float maChoose3 = ma[index3.code];
            float maChoose4 = ma[index4.code];
            BigDecimal degree2 = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose3), new BigDecimal(maChoose4));
            if (degree2.compareTo(degree1) > 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * ma均线斜率开空判断
     */
    @Override
    public Boolean maSellSlope_Open(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO, BigDecimal minDegree,
                                    BigDecimal maxDegree, MovingAveragePeriodEnum maPeriod,
                                    MovingAverageIndexEnum index1, MovingAverageIndexEnum index2) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 26);

        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        float maChoose1 = ma[index1.code];
        float maChoose2 = ma[index2.code];

        //指定级别周期
        BigDecimal degree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose1), new BigDecimal(maChoose2));

        //三个周期级别都满足斜率要求才能开空
        return (degree.compareTo(minDegree) > 0)
                &&
                (degree.compareTo(maxDegree) < 0);
    }

    /**
     * 开空两ma均线大小判断
     */
    public Boolean twoMaSellSlopeJudge_Open(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO,
                                            BigDecimal minDegree, BigDecimal maxDegree, MovingAveragePeriodEnum maPeriod,
                                            MovingAverageIndexEnum index1, MovingAverageIndexEnum index2,
                                            MovingAverageIndexEnum index3, MovingAverageIndexEnum index4) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 26);

        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        float maChoose1 = ma[index1.code];
        float maChoose2 = ma[index2.code];

        BigDecimal degree1 = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose1), new BigDecimal(maChoose2));

        if ((degree1.compareTo(minDegree) > 0) && (degree1.compareTo(maxDegree) < 0)) {
            float maChoose3 = ma[index3.code];
            float maChoose4 = ma[index4.code];
            BigDecimal degree2 = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose3), new BigDecimal(maChoose4));
            if (degree2.compareTo(degree1) < 0) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * ma均线斜率平多判断
     */
    @Override
    public Boolean maBuySlope_Close(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO, BigDecimal maxDegree,
                                    MovingAveragePeriodEnum maPeriod, MovingAverageIndexEnum index1, MovingAverageIndexEnum index2) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 26);

        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        float maChoose1 = ma[index1.code];
        float maChoose2 = ma[index2.code];

        //指定级别周期
        BigDecimal degree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose1), new BigDecimal(maChoose2));

        //指定周期级别满足斜率要求才能平多
        return degree.compareTo(maxDegree) <= 0;
    }

    /**
     * ma均线斜率平空判断
     */
    @Override
    public Boolean maSellSlope_Close(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO, BigDecimal minDegree,
                                     MovingAveragePeriodEnum maPeriod, MovingAverageIndexEnum index1, MovingAverageIndexEnum index2) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 26);

        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        float maChoose1 = ma[index1.code];
        float maChoose2 = ma[index2.code];

        //指定级别周期
        BigDecimal degree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(maChoose1), new BigDecimal(maChoose2));

        //指定周期级别满足斜率要求才能平空
        return degree.compareTo(minDegree) >= 0;
    }

    /**
     * ma均线多单偏离值判断
     */
    public Boolean maBuySlope_Departure(JSONObject candleStick, QuantBotDetailDTO quantBotDetailDTO, MovingAveragePeriodEnum maPeriod) throws Exception {
        BigDecimal departureRate = new BigDecimal(quantBotDetailDTO.getStopProfitBackRatio()).abs();

        float[] mas = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        JSONArray candlesticks = candleStick.getJSONArray("candlesticks");
        JSONObject nowCandlerStick = (JSONObject) (candlesticks.get(candlesticks.size() - 1));

        BigDecimal price = new BigDecimal(nowCandlerStick.getFloatValue("close"));
        BigDecimal maValue = new BigDecimal(mas[MovingAverageIndexEnum.NOW.code]);

        //Boolean judge1 = price.compareTo(maValue) > 0;

        Boolean judge2 = price.subtract(maValue).divide(maValue, 6, BigDecimal.ROUND_DOWN).abs().compareTo(departureRate) <= 0;

        return /*judge1 &&*/ judge2;
    }

    /**
     * ma均线空单偏离值判断
     */
    public Boolean maSellSlope_Departure(JSONObject candleStick, QuantBotDetailDTO quantBotDetailDTO, MovingAveragePeriodEnum maPeriod) throws Exception {
        BigDecimal departureRate = new BigDecimal(quantBotDetailDTO.getStopProfitBackRatio()).abs();

        float[] mas = iCalculatePriceService.calculateMA(candleStick, maPeriod);

        JSONArray candlesticks = candleStick.getJSONArray("candlesticks");
        JSONObject nowCandlerStick = (JSONObject) (candlesticks.get(candlesticks.size() - 1));

        BigDecimal price = new BigDecimal(nowCandlerStick.getFloatValue("close"));
        BigDecimal maValue = new BigDecimal(mas[MovingAverageIndexEnum.NOW.code]);

        //Boolean judge1 = price.compareTo(maValue) < 0;

        Boolean judge2 = price.subtract(maValue).divide(maValue, 6, BigDecimal.ROUND_DOWN).abs().compareTo(departureRate) <= 0;

        return /*judge1 &&*/ judge2;
    }

    /**
     * 开多向上三线开花判断
     */
    public Boolean judgeBuyFlower(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO, MovingAveragePeriodEnum smallMaPeriod,
                                  MovingAveragePeriodEnum midMaPeriod, MovingAveragePeriodEnum bigMaPeriod, MovingAverageIndexEnum index,
                                  MovingAverageIndexEnum degreeIndex1, MovingAverageIndexEnum degreeIndex2) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 480);
        float[] smallMas = iCalculatePriceService.calculateMA(candleStick, smallMaPeriod);
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMaPeriod);
        float[] bigMas = iCalculatePriceService.calculateMA(candleStick, bigMaPeriod);

        //小周期均线>中周期均线>大周期均线
        BigDecimal smallMa = new BigDecimal(smallMas[index.code]);
        BigDecimal midMa = new BigDecimal(midMas[index.code]);
        BigDecimal bigMa = new BigDecimal(bigMas[index.code]);

        //Boolean judge1 = (smallMa.compareTo(midMa) > 0) && (midMa.compareTo(bigMa) > 0);
        Boolean judge1 = (smallMa.compareTo(midMa) > 0) && (smallMa.compareTo(bigMa) > 0);

        //小周期均线斜率>中周期均线斜率>大周期均线斜率>0
        BigDecimal smallMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(smallMas[degreeIndex1.code]), new BigDecimal(smallMas[degreeIndex2.code]));
        BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(midMas[degreeIndex1.code]), new BigDecimal(midMas[degreeIndex2.code]));
        BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas[degreeIndex1.code]), new BigDecimal(bigMas[degreeIndex2.code]));

        Boolean judge2 = (smallMaDegree.compareTo(midMaDegree) > 0) && (midMaDegree.compareTo(bigMaDegree) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0);
        //Boolean judge2 = (smallMaDegree.compareTo(BigDecimal.ZERO) > 0) && (midMaDegree.compareTo(BigDecimal.ZERO) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0);

        //上根蜡烛图的收盘价>上根大周期均线
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry = candleEntries.get(candleEntries.size() - 3);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);

        BigDecimal lastClose = new BigDecimal(lastCandleEntry.getClose());
        BigDecimal lastBigMa = new BigDecimal(bigMas[MovingAverageIndexEnum.LAST.code]);

        Boolean judge3 = lastClose.compareTo(lastBigMa) > 0;

        if (interval == CandlestickInterval.ONE_MINUTE && judge1 && judge2 && judge3) {
            JSONObject candleStick2 = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                    quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIVE_MINUTES, null, null, 480);
            List<MyCandleEntry> candleEntries2 = getCandlerStick(candleStick2, quantBotDetailDTO);
            MyCandleEntry lastCandleEntry2 = candleEntries2.get(candleEntries2.size() - 2);

            BigDecimal lowestPrice = getLowestPrice(candleEntries, candleEntries.size() - 2, 2);

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry2.getLow()));
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(lowestPrice);
            pinBarCandlerStickDetailDTO.setStopLossRate((pinBarCandlerStickDetailDTO.getStopLossPrice().subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            //pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().compareTo(new BigDecimal("0.012")) >= 0 ? pinBarCandlerStickDetailDTO.getStopLossRate().abs() : new BigDecimal("0.012"));
            pinBarCandlerStickDetailDTO.setStopWinRate(new BigDecimal("0.01"));
            pinBarCandlerStickDetailDTO.setBreakEvenRate(new BigDecimal("0.001"));

            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        //三判断同时成立则返回true
        return judge1 && judge2 && judge3;
    }

    /**
     * 开空向下三线开花判断
     */
    public Boolean judgeSellFlower(CandlestickInterval interval, QuantBotDetailDTO quantBotDetailDTO, MovingAveragePeriodEnum smallMaPeriod,
                                   MovingAveragePeriodEnum midMaPeriod, MovingAveragePeriodEnum bigMaPeriod, MovingAverageIndexEnum index,
                                   MovingAverageIndexEnum degreeIndex1, MovingAverageIndexEnum degreeIndex2) throws Exception {
        JSONObject candleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), interval, null, null, 480);
        float[] smallMas = iCalculatePriceService.calculateMA(candleStick, smallMaPeriod);
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMaPeriod);
        float[] bigMas = iCalculatePriceService.calculateMA(candleStick, bigMaPeriod);

        //小周期均线<中周期均线<大周期均线
        BigDecimal smallMa = new BigDecimal(smallMas[index.code]);
        BigDecimal midMa = new BigDecimal(midMas[index.code]);
        BigDecimal bigMa = new BigDecimal(bigMas[index.code]);

        //Boolean judge1 = (smallMa.compareTo(midMa) < 0) && (midMa.compareTo(bigMa) < 0);
        Boolean judge1 = (smallMa.compareTo(midMa) < 0) && (smallMa.compareTo(bigMa) < 0);

        //小周期均线斜率<中周期均线斜率<大周期均线斜率<0
        BigDecimal smallMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(smallMas[degreeIndex1.code]), new BigDecimal(smallMas[degreeIndex2.code]));
        BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(midMas[degreeIndex1.code]), new BigDecimal(midMas[degreeIndex2.code]));
        BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas[degreeIndex1.code]), new BigDecimal(bigMas[degreeIndex2.code]));

        Boolean judge2 = (smallMaDegree.compareTo(midMaDegree) < 0) && (midMaDegree.compareTo(bigMaDegree) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0);
        //Boolean judge2 = (smallMaDegree.compareTo(BigDecimal.ZERO) < 0) && (midMaDegree.compareTo(BigDecimal.ZERO) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0);

        //上根蜡烛图的收盘价<上根大周期均线
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry = candleEntries.get(candleEntries.size() - 3);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        BigDecimal lastClose = new BigDecimal(lastCandleEntry.getClose());
        BigDecimal lastBigMa = new BigDecimal(bigMas[MovingAverageIndexEnum.LAST.code]);

        Boolean judge3 = lastClose.compareTo(lastBigMa) < 0;

        if (interval == CandlestickInterval.ONE_MINUTE && judge1 && judge2 && judge3) {
            JSONObject candleStick2 = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                    quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIVE_MINUTES, null, null, 480);
            List<MyCandleEntry> candleEntries2 = getCandlerStick(candleStick2, quantBotDetailDTO);
            MyCandleEntry lastCandleEntry2 = candleEntries2.get(candleEntries2.size() - 2);

            BigDecimal highestPrice = getHighestPrice(candleEntries, candleEntries.size() - 2, 2);

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry2.getHigh()));
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(highestPrice);
            pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(nowCandleEntry.getClose()).subtract(pinBarCandlerStickDetailDTO.getStopLossPrice())).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            //pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().compareTo(new BigDecimal("0.012")) >= 0 ? pinBarCandlerStickDetailDTO.getStopLossRate().abs() : new BigDecimal("0.012"));
            pinBarCandlerStickDetailDTO.setStopWinRate(new BigDecimal("0.01"));
            pinBarCandlerStickDetailDTO.setBreakEvenRate(new BigDecimal("0.001"));

            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.subtract(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        //三判断同时成立则返回true
        return judge1 && judge2 && judge3;
    }

    /**
     * 获取某根均线值
     */
    public BigDecimal getMa(JSONObject candleStick, MovingAveragePeriodEnum maPeriod, MovingAverageIndexEnum index) throws Exception {
        float[] ma = iCalculatePriceService.calculateMA(candleStick, maPeriod);
        float maChoose = ma[index.code];
        return new BigDecimal(maChoose);
    }

    /**
     * 开多均线金叉判断
     */
    public Boolean goldCrossOpen(JSONObject candleStick, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getPinbarTime()).compareTo(BigDecimal.ZERO) == 0) {
            List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
            MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
            Boolean open = (((getMa(candleStick, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST)).compareTo(getMa(candleStick, MovingAveragePeriodEnum.MA13, MovingAverageIndexEnum.LAST)) > 0) && ((getMa(candleStick, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST2)).compareTo(getMa(candleStick, MovingAveragePeriodEnum.MA13, MovingAverageIndexEnum.LAST2)) < 0) /*&& ((iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA13, MovingAverageIndexEnum.LAST)).compareTo(iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA21, MovingAverageIndexEnum.LAST)) > 0)*/)
                    /*|| (((iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST)).compareTo(iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA21, MovingAverageIndexEnum.LAST)) > 0) && ((iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST2)).compareTo(iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA21, MovingAverageIndexEnum.LAST2)) < 0))*/;
            if (open) {
                PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
      /*          pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry.getLow()));
                pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(lastCandleEntry.getLow()).subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
                pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().multiply(new BigDecimal("2")));
                pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));*/

                pinBarCandlerStickDetailDTO.setHigh(new BigDecimal(lastCandleEntry.getHigh()));
                pinBarCandlerStickDetailDTO.setLow(new BigDecimal(lastCandleEntry.getLow()));
                pinBarCandlerStickDetailDTO.setOpen(new BigDecimal(lastCandleEntry.getOpen()));
                pinBarCandlerStickDetailDTO.setClose(new BigDecimal(lastCandleEntry.getClose()));

                quantBotDetailDTO.setPinbarTime(String.valueOf(System.currentTimeMillis()));

                quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 开空均线死叉判断
     */
    public Boolean deathCrossOpen(JSONObject candleStick, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getPinbarTime()).compareTo(BigDecimal.ZERO) == 0) {
            List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
            MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
            MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);

            Boolean open = (((getMa(candleStick, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST)).compareTo(getMa(candleStick, MovingAveragePeriodEnum.MA13, MovingAverageIndexEnum.LAST)) < 0) && ((getMa(candleStick, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST2)).compareTo(getMa(candleStick, MovingAveragePeriodEnum.MA13, MovingAverageIndexEnum.LAST2)) > 0) /*&& ((iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA13, MovingAverageIndexEnum.LAST)).compareTo(iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA21, MovingAverageIndexEnum.LAST)) < 0)*/)
                    /*|| (((iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST)).compareTo(iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA21, MovingAverageIndexEnum.LAST)) < 0) && ((iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA5, MovingAverageIndexEnum.LAST2)).compareTo(iTechniqueSymbolService.getMa(interval, quantBotDetailDTO, MovingAveragePeriodEnum.MA21, MovingAverageIndexEnum.LAST2)) > 0))*/;

            if (open) {
                PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
                /*pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry.getHigh()));
                pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(nowCandleEntry.getClose()).subtract(new BigDecimal(lastCandleEntry.getHigh()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
                pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().multiply(new BigDecimal("2")));
                pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.subtract(pinBarCandlerStickDetailDTO.getStopWinRate())));*/

                pinBarCandlerStickDetailDTO.setHigh(new BigDecimal(lastCandleEntry.getHigh()));
                pinBarCandlerStickDetailDTO.setLow(new BigDecimal(lastCandleEntry.getLow()));
                pinBarCandlerStickDetailDTO.setOpen(new BigDecimal(lastCandleEntry.getOpen()));
                pinBarCandlerStickDetailDTO.setClose(new BigDecimal(lastCandleEntry.getClose()));

                quantBotDetailDTO.setPinbarTime(String.valueOf(System.currentTimeMillis()));

                quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 运行过程中均线金叉判断
     */
    public Boolean goldCrossRunning(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum longMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getCrossTime()).compareTo(BigDecimal.ZERO) == 0) {
            if (((getMa(candleStick, shortMa, MovingAverageIndexEnum.LAST)).compareTo(getMa(candleStick, longMa, MovingAverageIndexEnum.LAST)) >= 0) && ((getMa(candleStick, shortMa, MovingAverageIndexEnum.LAST2)).compareTo(getMa(candleStick, longMa, MovingAverageIndexEnum.LAST2)) <= 0)) {
                List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
                BigDecimal highestPrice = getHighestPrice(candleEntries, candleEntries.size() - 1, 16);
                PinBarCandlerStickDetailDTO dto = quantBotDetailDTO.getPinBarCandlerStickDetailDTO();
                dto.setStopLossPrice(highestPrice);
                quantBotDetailDTO.setPinBarCandlerStickDetailDTO(dto);

                quantBotDetailDTO.setCrossTime(String.valueOf(System.currentTimeMillis()));

                //if (dto.getStopLossPrice().compareTo(new BigDecimal(quantBotDetailDTO.getAvgPrice())) <= 0) {
                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
                //}
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 运行过程中均线金叉是否确认成立判断
     */
    public Boolean judgeBuyTendencyRunning(List<MyCandleEntry> candleEntries, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getCrossTime()).compareTo(BigDecimal.ZERO) == 0) {
            return false;
        } else {
            BigDecimal crossTime = new BigDecimal(quantBotDetailDTO.getCrossTime());
            BigDecimal nowTime = new BigDecimal(System.currentTimeMillis());
            BigDecimal intevalStart = new BigDecimal("300000");
            BigDecimal intevalEnd = new BigDecimal("1500000");
            BigDecimal subtract = nowTime.subtract(crossTime);
            if (subtract.compareTo(intevalStart) < 0) {
                return false;
            } else if (subtract.compareTo(intevalStart) >= 0 && subtract.compareTo(intevalEnd) <= 0) {
                MyCandleEntry myCandleEntry = candleEntries.get(candleEntries.size() - 2);
                if (new BigDecimal(myCandleEntry.getClose()).compareTo(quantBotDetailDTO.getPinBarCandlerStickDetailDTO().getStopLossPrice()) >= 0) {
                    return true;
                } else {
                    return false;
                }
            } else {
                quantBotDetailDTO.setCrossTime("0");
                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
                return false;
            }
        }
    }

    /**
     * 运行过程中均线死叉判断
     */
    public Boolean deathCrossRunning(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum longMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getCrossTime()).compareTo(BigDecimal.ZERO) == 0) {
            if (((getMa(candleStick, shortMa, MovingAverageIndexEnum.LAST)).compareTo(getMa(candleStick, longMa, MovingAverageIndexEnum.LAST)) <= 0) && ((getMa(candleStick, shortMa, MovingAverageIndexEnum.LAST2)).compareTo(getMa(candleStick, longMa, MovingAverageIndexEnum.LAST2)) >= 0)) {
                List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
                BigDecimal lowestPrice = getLowestPrice(candleEntries, candleEntries.size() - 1, 16);
                PinBarCandlerStickDetailDTO dto = quantBotDetailDTO.getPinBarCandlerStickDetailDTO();
                dto.setStopLossPrice(lowestPrice);
                quantBotDetailDTO.setPinBarCandlerStickDetailDTO(dto);

                quantBotDetailDTO.setCrossTime(String.valueOf(System.currentTimeMillis()));

                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 运行过程中均线死叉是否确认成立判断
     */
    public Boolean judgeSellTendencyRunning(List<MyCandleEntry> candleEntries, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getCrossTime()).compareTo(BigDecimal.ZERO) == 0) {
            return false;
        } else {
            BigDecimal crossTime = new BigDecimal(quantBotDetailDTO.getCrossTime());
            BigDecimal nowTime = new BigDecimal(System.currentTimeMillis());
            BigDecimal intevalStart = new BigDecimal("300000");
            BigDecimal intevalEnd = new BigDecimal("1500000");
            BigDecimal subtract = nowTime.subtract(crossTime);
            if (subtract.compareTo(intevalStart) < 0) {
                return false;
            } else if (subtract.compareTo(intevalStart) >= 0 && subtract.compareTo(intevalEnd) <= 0) {
                MyCandleEntry myCandleEntry = candleEntries.get(candleEntries.size() - 2);
                if (new BigDecimal(myCandleEntry.getClose()).compareTo(quantBotDetailDTO.getPinBarCandlerStickDetailDTO().getStopLossPrice()) <= 0) {
                    return true;
                } else {
                    return false;
                }
            } else {
                quantBotDetailDTO.setCrossTime("0");

                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
                return false;
            }
        }
    }

    //----------------------------------------------------------------------------------------------------------------------

    //---------------------------------------------------蜡烛图判断-------------------------------------------------

    /**
     * 多单开仓和加仓对某根蜡烛图的判断
     */
    public Boolean candle_Buy_OpenAdd(JSONObject candleSticks, BigDecimal ratio, int candleIndex) {
        JSONArray candlesticks = candleSticks.getJSONArray("candlesticks");
        List<MyCandleEntry> candleEntries = new ArrayList<>();
        for (int i = 0; i < candlesticks.size(); i++) {
            JSONObject obj = (JSONObject) (candlesticks.get(i));
            MyCandleEntry candleEntry = new MyCandleEntry(i, obj.getFloatValue("high"), obj.getFloatValue("low"), obj.getFloatValue("open"), obj.getFloatValue("close"), obj.getFloatValue("volume"), obj.getLongValue("openTime"), obj.getLongValue("closeTime"), obj.getBigDecimal("quoteAssetVolume"));
            candleEntries.add(candleEntry);
        }

        MyCandleEntry myCandleEntry = candleEntries.get(candleEntries.size() - candleIndex);
        BigDecimal close = new BigDecimal(myCandleEntry.getClose());
        BigDecimal open = new BigDecimal(myCandleEntry.getOpen());

        return ((close.subtract(open)).divide(open, 6, BigDecimal.ROUND_DOWN)).compareTo(ratio) <= 0;
    }

    /**
     * 空单开仓和加仓对某根蜡烛图的判断
     */
    public Boolean candle_Sell_OpenAdd(JSONObject candleSticks, BigDecimal ratio, int candleIndex) {
        JSONArray candlesticks = candleSticks.getJSONArray("candlesticks");
        List<MyCandleEntry> candleEntries = new ArrayList<>();
        for (int i = 0; i < candlesticks.size(); i++) {
            JSONObject obj = (JSONObject) (candlesticks.get(i));
            MyCandleEntry candleEntry = new MyCandleEntry(i, obj.getFloatValue("high"), obj.getFloatValue("low"), obj.getFloatValue("open"), obj.getFloatValue("close"), obj.getFloatValue("volume"), obj.getLongValue("openTime"), obj.getLongValue("closeTime"), obj.getBigDecimal("quoteAssetVolume"));
            candleEntries.add(candleEntry);
        }

        MyCandleEntry myCandleEntry = candleEntries.get(candleEntries.size() - candleIndex);
        BigDecimal close = new BigDecimal(myCandleEntry.getClose());
        BigDecimal open = new BigDecimal(myCandleEntry.getOpen());

        return ((close.subtract(open)).divide(open, 6, BigDecimal.ROUND_DOWN)).compareTo(ratio) >= 0;
    }

    /**
     * 获取某根蜡烛
     */
    public List<MyCandleEntry> getCandlerStick(JSONObject candleStick, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        JSONArray candlesticks = candleStick.getJSONArray("candlesticks");
        List<MyCandleEntry> candleEntries = new ArrayList<>();
        for (int i = 0; i < candlesticks.size(); i++) {
            JSONObject obj = (JSONObject) (candlesticks.get(i));
            MyCandleEntry candleEntry = new MyCandleEntry(i, obj.getFloatValue("high"), obj.getFloatValue("low"), obj.getFloatValue("open"), obj.getFloatValue("close"), obj.getFloatValue("volume"), obj.getLongValue("openTime"), obj.getLongValue("closeTime"), obj.getBigDecimal("quoteAssetVolume"));
            candleEntries.add(candleEntry);
        }

        return candleEntries;
    }

    /**
     * 获取某段时间内最高价格
     */
    public BigDecimal getHighestPrice(List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal highestPrice = new BigDecimal(candleEntries.get(index).getClose());
        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getHigh());
            highestPrice = tempPrice.compareTo(highestPrice) > 0 ? tempPrice : highestPrice;
        }

        return highestPrice;
    }

    /**
     * 获取某段时间内最高价格和那根ATR
     */
    public BigDecimal[] getHighestPriceAndAtr(List<Num> atrs, List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal highestPrice = new BigDecimal(candleEntries.get(index).getClose());
        int chooseIndex = 0;

        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getHigh());
            Boolean judge = tempPrice.compareTo(highestPrice) > 0;
            highestPrice = judge ? tempPrice : highestPrice;
            chooseIndex = judge ? i : chooseIndex;
        }
        BigDecimal chooseAtr = new BigDecimal(atrs.get(atrs.size() - 2 - chooseIndex).floatValue());

        BigDecimal[] results = new BigDecimal[2];
        results[0] = highestPrice;
        results[1] = chooseAtr;
        return results;
    }

    /**
     * 获取某段时间内最低价格
     */
    public BigDecimal getLowestPrice(List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal lowestPrice = new BigDecimal(candleEntries.get(index).getClose());
        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getLow());
            lowestPrice = tempPrice.compareTo(lowestPrice) < 0 ? tempPrice : lowestPrice;
        }

        return lowestPrice;
    }

    /**
     * 获取某段时间内最低价格和那根ATR
     */
    public BigDecimal[] getLowestPriceAndAtr(List<Num> atrs, List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal lowestPrice = new BigDecimal(candleEntries.get(index).getClose());
        int chooseIndex = 0;

        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempPrice = new BigDecimal(candleEntry.getLow());
            Boolean judge = tempPrice.compareTo(lowestPrice) < 0;
            lowestPrice = judge ? tempPrice : lowestPrice;
            chooseIndex = judge ? i : chooseIndex;
        }
        BigDecimal chooseAtr = new BigDecimal(atrs.get(atrs.size() - 2 - chooseIndex).floatValue());

        BigDecimal[] results = new BigDecimal[2];
        results[0] = lowestPrice;
        results[1] = chooseAtr;
        return results;
    }

    /**
     * 获取某段时间内最大成交量
     */
    public BigDecimal getHighestVolume(List<MyCandleEntry> candleEntries, int index, int period) throws Exception {
        BigDecimal highestVolume = new BigDecimal(candleEntries.get(index).getVolume());
        for (int i = 0; i < period; i++) {
            MyCandleEntry candleEntry = candleEntries.get(index - i);
            BigDecimal tempVolume = new BigDecimal(candleEntry.getVolume());
            highestVolume = tempVolume.compareTo(highestVolume) > 0 ? tempVolume : highestVolume;
        }

        return highestVolume;
    }

    /**
     * 开多吞没pinbar判断
     */
    public Boolean judgeBuyPinBarOpen(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
        float[] longMas = iCalculatePriceService.calculateMA(candleStick, longMa);

        //中周期均线<大周期均线
        BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]);
        BigDecimal bigMaValue = new BigDecimal(longMas[MovingAverageIndexEnum.LAST.code]);

        Boolean judge1 = midMaValue.compareTo(bigMaValue) < 0;

        //中周期均线斜率<0,大周期均线斜率<0
        BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(midMas[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(longMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(longMas[MovingAverageIndexEnum.LAST2.code]));

        Boolean judge2 = (midMaDegree.compareTo(BigDecimal.ZERO) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0);

        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);

        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry = candleEntries.get(candleEntries.size() - 3);
        //上上根蜡烛的开盘价-上上根蜡烛的收盘价
        BigDecimal subtract1 = new BigDecimal(last2CandleEntry.getOpen()).subtract(new BigDecimal(last2CandleEntry.getClose()));
        //上根蜡烛收盘价-上根蜡烛开盘价
        BigDecimal subtract2 = new BigDecimal(lastCandleEntry.getClose()).subtract(new BigDecimal(lastCandleEntry.getOpen()));
        //上根蜡烛开盘价-上根蜡烛最低点
        BigDecimal subtract3 = new BigDecimal(lastCandleEntry.getOpen()).subtract(new BigDecimal(lastCandleEntry.getLow()));
        //上根蜡烛最高点-上根蜡烛最低点
        BigDecimal subtract4 = new BigDecimal(lastCandleEntry.getHigh()).subtract(new BigDecimal(lastCandleEntry.getLow()));

        //上根蜡烛图实体大于等于阈值才可开仓
        BigDecimal candleStickLength = subtract2.divide(new BigDecimal(lastCandleEntry.getOpen()), 6, BigDecimal.ROUND_DOWN).abs();

        boolean open = judge1 && judge2 && (subtract1.compareTo(BigDecimal.ZERO) > 0) && (subtract2.compareTo(subtract1) > 0) && (subtract3.divide(subtract4, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.5")) > 0);

        if (open) {
            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry.getLow()));
            pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(lastCandleEntry.getLow()).subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().multiply(new BigDecimal("2")));
            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        return open;
    }

    /**
     * 开空吞没pinbar判断
     */
    public Boolean judgeSellPinBarOpen(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
        float[] longMas = iCalculatePriceService.calculateMA(candleStick, longMa);

        //中周期均线>大周期均线
        BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]);
        BigDecimal bigMaValue = new BigDecimal(longMas[MovingAverageIndexEnum.LAST.code]);

        Boolean judge1 = midMaValue.compareTo(bigMaValue) > 0;

        //中周期均线斜率>0,大周期均线斜率>0
        BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(midMas[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(longMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(longMas[MovingAverageIndexEnum.LAST2.code]));

        Boolean judge2 = (midMaDegree.compareTo(BigDecimal.ZERO) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0);

        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);

        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        MyCandleEntry last2CandleEntry = candleEntries.get(candleEntries.size() - 3);
        //上上根蜡烛的收盘价-上上根蜡烛的开盘价
        BigDecimal subtract1 = new BigDecimal(last2CandleEntry.getClose()).subtract(new BigDecimal(last2CandleEntry.getOpen()));
        //上根蜡烛开盘价-上根蜡烛收盘价
        BigDecimal subtract2 = new BigDecimal(lastCandleEntry.getOpen()).subtract(new BigDecimal(lastCandleEntry.getClose()));
        //上根蜡烛最高点-上根蜡烛开盘价
        BigDecimal subtract3 = new BigDecimal(lastCandleEntry.getHigh()).subtract(new BigDecimal(lastCandleEntry.getOpen()));
        //上根蜡烛最高点-上根蜡烛最低点
        BigDecimal subtract4 = new BigDecimal(lastCandleEntry.getHigh()).subtract(new BigDecimal(lastCandleEntry.getLow()));

        //上根蜡烛图实体大于等于阈值才可开仓
        BigDecimal candleStickLength = subtract2.divide(new BigDecimal(lastCandleEntry.getOpen()), 6, BigDecimal.ROUND_DOWN).abs();

        boolean open = judge1 && judge2 && (subtract1.compareTo(BigDecimal.ZERO) > 0) && (subtract2.compareTo(subtract1) > 0) && (subtract3.divide(subtract4, 6, BigDecimal.ROUND_DOWN).compareTo(new BigDecimal("0.5")) > 0);

        if (open) {
            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry.getHigh()));
            pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(nowCandleEntry.getClose()).subtract(new BigDecimal(lastCandleEntry.getHigh()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().multiply(new BigDecimal("2")));
            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.subtract(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        return open;
    }

    /**
     * 开多趋势中pinbar判断
     */
    public Boolean judgeTrendBuyPinBarOpen(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getPinbarTime()).compareTo(BigDecimal.ZERO) == 0) {
            float[] smallMas = iCalculatePriceService.calculateMA(candleStick, shortMa);
            float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
            float[] bigMas = iCalculatePriceService.calculateMA(candleStick, longMa);

            //小周期均线>中周期均线>大周期均线
            BigDecimal smallMaValue = new BigDecimal(smallMas[MovingAverageIndexEnum.LAST.code]);
            BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]);
            BigDecimal bigMaValue = new BigDecimal(bigMas[MovingAverageIndexEnum.LAST.code]);

            Boolean judge1 = midMaValue.compareTo(bigMaValue) > 0;

            //小周期均线<0,中周期均线斜率<0,大周期均线斜率<0
            BigDecimal smallMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(smallMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(smallMas[MovingAverageIndexEnum.LAST2.code]));
            BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(midMas[MovingAverageIndexEnum.LAST2.code]));
            BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(bigMas[MovingAverageIndexEnum.LAST2.code]));

            Boolean judge2 = (smallMaDegree.compareTo(BigDecimal.ZERO) < 0) && (midMaDegree.compareTo(BigDecimal.ZERO) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0);

            List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);

            MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
            MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);

            Boolean judge3 = new BigDecimal(lastCandleEntry.getClose()).compareTo(new BigDecimal(lastCandleEntry.getOpen())) > 0;

            BigDecimal subtract1 = new BigDecimal(lastCandleEntry.getOpen()).subtract(new BigDecimal(lastCandleEntry.getLow()));
            BigDecimal subtract2 = new BigDecimal(lastCandleEntry.getHigh()).subtract(new BigDecimal(lastCandleEntry.getLow()));
            Boolean judge4 = (subtract1.divide(subtract2, 6, BigDecimal.ROUND_DOWN)).compareTo(new BigDecimal("0.5")) > 0;

            Boolean judge5 = /*(new BigDecimal(lastCandleEntry.getHigh()).compareTo(smallMaValue) <= 0)
                    && (new BigDecimal(lastCandleEntry.getHigh()).compareTo(midMaValue) <= 0)
                    && */(new BigDecimal(lastCandleEntry.getHigh()).compareTo(bigMaValue) <= 0);

            Boolean open = judge2 && judge3 && judge4 && judge5;

            if (open) {
                PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
      /*          pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry.getLow()));
                pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(lastCandleEntry.getLow()).subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
                pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().multiply(new BigDecimal("2")));
                pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));*/

                pinBarCandlerStickDetailDTO.setHigh(new BigDecimal(lastCandleEntry.getHigh()));
                pinBarCandlerStickDetailDTO.setLow(new BigDecimal(lastCandleEntry.getLow()));
                pinBarCandlerStickDetailDTO.setOpen(new BigDecimal(lastCandleEntry.getOpen()));
                pinBarCandlerStickDetailDTO.setClose(new BigDecimal(lastCandleEntry.getClose()));

                quantBotDetailDTO.setPinbarTime(String.valueOf(System.currentTimeMillis()));

                quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 开多趋势中突破判断
     */
    public Boolean judgeTrendBuyBreakThroughOpen(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, Duration barSeriesTimePeriod) throws Exception {
        int judgePeriod = 1;

        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        BarSeries barSeries = getBarSeries(candleEntries, barSeriesTimePeriod);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        List<Entry> emas200 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA200);
        BigDecimal lastEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2)).getY());

        int diBarCount = 14;
        int adxBarCount = 14;
        double lastAdx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 1);

        int rsiBarCount = 14;
        int stockBarCount = 14;
        int kPeriod = 6;
        int dPeriod = 6;
        Num[] lastStochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 1);
        Num[] last2StochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 2);
        Num lastStochK = lastStochRsi[0];
        Num lastStochD = lastStochRsi[1];
        Num last2StochK = last2StochRsi[0];
        Num last2StochD = last2StochRsi[1];

        if (new BigDecimal(lastCandleEntry.getClose()).compareTo(lastEmaValue200) > 0 &&
                lastAdx > 50 &&
                last2StochK.isLessThan(last2StochD) && lastStochK.isGreaterThan(lastStochD) &&
                lastStochK.isLessThan(barSeries.numOf(20)) && lastStochD.isLessThan(barSeries.numOf(20))
        ) {
            List<Num> atrs = getATR(barSeries, atrPeriod);
            BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, judgePeriod);
            BigDecimal nowOpen = new BigDecimal(nowCandleEntry.getOpen());
            BigDecimal lowestPrice = lowestAndAtr[0];
            BigDecimal lowestAtr = lowestAndAtr[1];
            BigDecimal initStopLossPrice = lowestPrice.subtract(lowestAtr.multiply(new BigDecimal("3.5")));
            BigDecimal initStopLossRate = nowOpen.subtract(initStopLossPrice).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();

            /*if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) >= 0) {
                return false;
            }*/

            BigDecimal stopLossRate = initStopLossRate;
            BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("0.85"));
            BigDecimal breakEvenRate = stopWinRatio;

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowOpen);

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            return true;
        } else {
            return false;
        }
    }

    /**
     * 开多趋势中突破判断
     */
    public Boolean judgeTrendBuyBreakThroughOpen2(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, Duration barSeriesTimePeriod) throws Exception {
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        BarSeries barSeries = getBarSeries(candleEntries, barSeriesTimePeriod);
        List<Num> atrs = getATR(barSeries, atrPeriod);
        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal nowClose = new BigDecimal(nowCandleEntry.getClose());

        BigDecimal[] highestAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 3, 20);
        BigDecimal highestPrice = highestAndAtr[0];

        if (new BigDecimal(lastCandleEntry.getClose()).compareTo(highestPrice) > 0) {
            BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, 20);
            BigDecimal lowestPrice = lowestAndAtr[0];
            BigDecimal lowestAtr = lowestAndAtr[1];
            BigDecimal initStopLossPrice = lowestPrice.subtract(lowestAtr.multiply(new BigDecimal("0")));
            BigDecimal initStopLossRate = nowClose.subtract(initStopLossPrice).divide(nowClose, 6, BigDecimal.ROUND_DOWN).abs();
            if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) >= 0) {
                return false;
            }

            BigDecimal stopLossRate = initStopLossRate;
            //BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("1.2"));
            BigDecimal stopWinRatio = new BigDecimal("0.01");
            //BigDecimal stopWinRatio = askPriceByMaxVolume.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            //BigDecimal breakEvenRate = stopWinRatio;
            BigDecimal breakEvenRate = new BigDecimal("0.005");

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowClose);

            //quantBotDetailDTO.setMinFall(String.valueOf(depthMid));
            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            return true;
        } else {
            return false;
        }
    }

    /**
     * 开多是否确认成立判断
     */
    public Boolean judgeBuyTendencyOpen1(QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        Boolean[] result1 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.TWO_HOURLY);
        Boolean[] result2 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.HALF_HOURLY);
        Boolean[] result3 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.HOURLY);
        //中周期确认方向，上根K收盘价大于上根21日均线
        JSONObject midCandleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIVE_MINUTES, null, null, 480);
        List<MyCandleEntry> midCandleEntries = getCandlerStick(midCandleStick, quantBotDetailDTO);
        MyCandleEntry lastMidCandleEntry = midCandleEntries.get(midCandleEntries.size() - 1);
        float[] midMas21 = iCalculatePriceService.calculateMA(midCandleStick, MovingAveragePeriodEnum.MA21);
        BigDecimal midMaValue21Last = new BigDecimal(midMas21[MovingAverageIndexEnum.NOW.code]);
        boolean confirmDirection = new BigDecimal(lastMidCandleEntry.getClose()).compareTo(midMaValue21Last) > 0;

        boolean result = result2[0] && confirmDirection;

        return result && result1[1] && result2[1] && result3[1];
    }

    public Boolean judgeBuyTendencyOpen2(QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        Boolean[] result1 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.TWO_HOURLY);
        Boolean[] result2 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.HALF_HOURLY);
        Boolean[] result3 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.HOURLY);
        //中周期确认方向，上根K收盘价大于上根21日均线
        JSONObject midCandleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIVE_MINUTES, null, null, 480);
        List<MyCandleEntry> midCandleEntries = getCandlerStick(midCandleStick, quantBotDetailDTO);
        MyCandleEntry lastMidCandleEntry = midCandleEntries.get(midCandleEntries.size() - 1);
        float[] midMas21 = iCalculatePriceService.calculateMA(midCandleStick, MovingAveragePeriodEnum.MA21);
        BigDecimal midMaValue21Last = new BigDecimal(midMas21[MovingAverageIndexEnum.NOW.code]);
        boolean confirmDirection = new BigDecimal(lastMidCandleEntry.getClose()).compareTo(midMaValue21Last) > 0;

        boolean result = result2[0] && confirmDirection;

        return result && result1[4] && result2[3] && result3[1];
    }

    /**
     * 开空趋势中pinbar判断
     */
    public Boolean judgeTrendSellPinBarOpen(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        if (new BigDecimal(quantBotDetailDTO.getPinbarTime()).compareTo(BigDecimal.ZERO) == 0) {
            float[] smallMas = iCalculatePriceService.calculateMA(candleStick, shortMa);
            float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
            float[] bigMas = iCalculatePriceService.calculateMA(candleStick, longMa);

            //中周期均线<大周期均线
            BigDecimal smallMaValue = new BigDecimal(smallMas[MovingAverageIndexEnum.LAST.code]);
            BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]);
            BigDecimal bigMaValue = new BigDecimal(bigMas[MovingAverageIndexEnum.LAST.code]);

            //Boolean judge1 = midMaValue.compareTo(bigMaValue) < 0;

            //小周期均线斜率>0,中周期均线斜率>0,大周期均线斜率>0
            BigDecimal smallMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(smallMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(smallMas[MovingAverageIndexEnum.LAST2.code]));
            BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(midMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(midMas[MovingAverageIndexEnum.LAST2.code]));
            BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas[MovingAverageIndexEnum.LAST.code]), new BigDecimal(bigMas[MovingAverageIndexEnum.LAST2.code]));

            Boolean judge2 = (smallMaDegree.compareTo(BigDecimal.ZERO) > 0) && (midMaDegree.compareTo(BigDecimal.ZERO) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0);

            List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);

            MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
            MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);

            Boolean judge3 = new BigDecimal(lastCandleEntry.getClose()).compareTo(new BigDecimal(lastCandleEntry.getOpen())) < 0;

            BigDecimal subtract1 = new BigDecimal(lastCandleEntry.getHigh()).subtract(new BigDecimal(lastCandleEntry.getOpen()));
            BigDecimal subtract2 = new BigDecimal(lastCandleEntry.getHigh()).subtract(new BigDecimal(lastCandleEntry.getLow()));
            Boolean judge4 = (subtract1.divide(subtract2, 6, BigDecimal.ROUND_DOWN)).compareTo(new BigDecimal("0.5")) > 0;

            Boolean judge5 = /*(new BigDecimal(lastCandleEntry.getLow()).compareTo(smallMaValue) >= 0)
                    && (new BigDecimal(lastCandleEntry.getLow()).compareTo(midMaValue) >= 0)
                    &&*/ (new BigDecimal(lastCandleEntry.getLow()).compareTo(bigMaValue) >= 0);

            Boolean open = judge2 && judge3 && judge4 && judge5;

            if (open) {
                PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
                /*pinBarCandlerStickDetailDTO.setStopLossPrice(new BigDecimal(lastCandleEntry.getHigh()));
                pinBarCandlerStickDetailDTO.setStopLossRate((new BigDecimal(nowCandleEntry.getClose()).subtract(new BigDecimal(lastCandleEntry.getHigh()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
                pinBarCandlerStickDetailDTO.setStopWinRate(pinBarCandlerStickDetailDTO.getStopLossRate().abs().multiply(new BigDecimal("2")));
                pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.subtract(pinBarCandlerStickDetailDTO.getStopWinRate())));*/

                pinBarCandlerStickDetailDTO.setHigh(new BigDecimal(lastCandleEntry.getHigh()));
                pinBarCandlerStickDetailDTO.setLow(new BigDecimal(lastCandleEntry.getLow()));
                pinBarCandlerStickDetailDTO.setOpen(new BigDecimal(lastCandleEntry.getOpen()));
                pinBarCandlerStickDetailDTO.setClose(new BigDecimal(lastCandleEntry.getClose()));

                quantBotDetailDTO.setPinbarTime(String.valueOf(System.currentTimeMillis()));

                quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);

                //更新交易对详情
                String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
                stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 开空趋势中突破判断
     */
    public Boolean judgeTrendSellBreakThroughOpen(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, Duration barSeriesTimePeriod) throws Exception {
        int judgePeriod = 1;

        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        BarSeries barSeries = getBarSeries(candleEntries, barSeriesTimePeriod);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        List<Entry> emas200 = iCalculatePriceService.calculateEMA(candleStick, MovingAveragePeriodEnum.MA200);
        BigDecimal lastEmaValue200 = new BigDecimal((emas200.get(emas200.size() - 2)).getY());

        int diBarCount = 14;
        int adxBarCount = 14;
        double lastAdx = getADX(barSeries, diBarCount, adxBarCount, barSeries.getEndIndex() - 1);

        int rsiBarCount = 14;
        int stockBarCount = 14;
        int kPeriod = 6;
        int dPeriod = 6;
        Num[] lastStochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 1);
        Num[] last2StochRsi = getStochRsi(barSeries, rsiBarCount, stockBarCount, kPeriod, dPeriod, barSeries.getEndIndex() - 2);
        Num lastStochK = lastStochRsi[0];
        Num lastStochD = lastStochRsi[1];
        Num last2StochK = last2StochRsi[0];
        Num last2StochD = last2StochRsi[1];

        if (new BigDecimal(lastCandleEntry.getClose()).compareTo(lastEmaValue200) < 0 &&
                lastAdx > 50 &&
                last2StochK.isGreaterThan(last2StochD) && lastStochK.isLessThan(lastStochD)
                && lastStochK.isGreaterThan(barSeries.numOf(80)) && lastStochD.isGreaterThan(barSeries.numOf(80))
        ) {
            List<Num> atrs = getATR(barSeries, atrPeriod);
            BigDecimal[] highestPriceAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, judgePeriod);
            BigDecimal highestPrice = highestPriceAndAtr[0];
            BigDecimal highestAtr = highestPriceAndAtr[1];
            BigDecimal nowOpen = new BigDecimal(nowCandleEntry.getOpen());
            BigDecimal initStopLossPrice = highestPrice.add(highestAtr.multiply(new BigDecimal("3.5")));
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();

            /*if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) >= 0) {
                return false;
            }*/

            BigDecimal stopLossRate = initStopLossRate;
            BigDecimal stopWinRatio = initStopLossRate.multiply(new BigDecimal("0.85"));
            BigDecimal breakEvenRate = stopWinRatio;

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowOpen);

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            return true;
        } else {
            return false;
        }
    }

    /**
     * 开空趋势中突破判断
     */
    public Boolean judgeTrendSellBreakThroughOpen2(JSONObject candleStick, int atrPeriod, QuantBotDetailDTO quantBotDetailDTO, Duration barSeriesTimePeriod) throws Exception {
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        MyCandleEntry lastCandleEntry = candleEntries.get(candleEntries.size() - 2);
        BarSeries barSeries = getBarSeries(candleEntries, barSeriesTimePeriod);
        List<Num> atrs = getATR(barSeries, atrPeriod);
        BigDecimal lastAtr = new BigDecimal(atrs.get(atrs.size() - 2).floatValue());
        BigDecimal nowClose = new BigDecimal(nowCandleEntry.getClose());

        BigDecimal[] lowestAndAtr = getLowestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 3, 20);
        BigDecimal lowestPrice = lowestAndAtr[0];

        if (new BigDecimal(lastCandleEntry.getClose()).compareTo(lowestPrice) < 0) {
            BigDecimal[] highestPriceAndAtr = getHighestPriceAndAtr(atrs, candleEntries, candleEntries.size() - 2, 20);
            BigDecimal highestPrice = highestPriceAndAtr[0];
            BigDecimal highestAtr = highestPriceAndAtr[1];
            BigDecimal initStopLossPrice = highestPrice.add(highestAtr.multiply(new BigDecimal("0")));
            BigDecimal initStopLossRate = initStopLossPrice.subtract(nowClose).divide(nowClose, 6, BigDecimal.ROUND_DOWN).abs();
            if (initStopLossRate.compareTo(SystemParamContants.stop_loss_max) >= 0) {
                return false;
            }

            BigDecimal stopLossRate = initStopLossRate;
            BigDecimal stopWinRatio = new BigDecimal("0.01");
            //BigDecimal stopWinRatio = SystemParamContants.fee;
            //BigDecimal stopWinRatio = askPriceByMaxVolume.subtract(nowOpen).divide(nowOpen, 6, BigDecimal.ROUND_DOWN).abs();
            BigDecimal breakEvenRate = new BigDecimal("0.005");

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopWinRate(stopWinRatio);
            pinBarCandlerStickDetailDTO.setBreakEvenRate(breakEvenRate);
            pinBarCandlerStickDetailDTO.setStopLossRate(stopLossRate);
            pinBarCandlerStickDetailDTO.setOpen(nowClose);

            //quantBotDetailDTO.setMinFall(String.valueOf(depthMid));
            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
            return true;
        } else {
            return false;
        }
    }

    /**
     * 开空是否确认成立判断
     */
    public Boolean judgeSellTendencyOpen1(QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        Boolean[] result1 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.TWO_HOURLY);
        Boolean[] result2 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.HALF_HOURLY);
        Boolean[] result3 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.HOURLY);

        //中周期确认方向，上根K收盘价小于上根21日均线
        JSONObject midCandleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIVE_MINUTES, null, null, 480);
        List<MyCandleEntry> midCandleEntries = getCandlerStick(midCandleStick, quantBotDetailDTO);
        MyCandleEntry lastMidCandleEntry = midCandleEntries.get(midCandleEntries.size() - 1);
        float[] midMas21 = iCalculatePriceService.calculateMA(midCandleStick, MovingAveragePeriodEnum.MA21);
        BigDecimal midMaValue21Last = new BigDecimal(midMas21[MovingAverageIndexEnum.NOW.code]);
        boolean confirmDirection = new BigDecimal(lastMidCandleEntry.getClose()).compareTo(midMaValue21Last) < 0;

        boolean result = result2[0] && confirmDirection;

        return result && result1[1] && result2[1] && result3[1];
    }

    public Boolean judgeSellTendencyOpen2(QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        Boolean[] result1 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.TWO_HOURLY);
        Boolean[] result2 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.HALF_HOURLY);
        Boolean[] result3 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.HOURLY);

        //中周期确认方向，上根K收盘价小于上根21日均线
        JSONObject midCandleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIVE_MINUTES, null, null, 480);
        List<MyCandleEntry> midCandleEntries = getCandlerStick(midCandleStick, quantBotDetailDTO);
        MyCandleEntry lastMidCandleEntry = midCandleEntries.get(midCandleEntries.size() - 1);
        float[] midMas21 = iCalculatePriceService.calculateMA(midCandleStick, MovingAveragePeriodEnum.MA21);
        BigDecimal midMaValue21Last = new BigDecimal(midMas21[MovingAverageIndexEnum.NOW.code]);
        boolean confirmDirection = new BigDecimal(lastMidCandleEntry.getClose()).compareTo(midMaValue21Last) < 0;

        boolean result = result2[0] && confirmDirection;

        return result && result1[4] && result2[3] && result3[1];
    }

    public Boolean judgeBuy1(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, MovingAveragePeriodEnum topMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        float[] shortMas = iCalculatePriceService.calculateMA(candleStick, shortMa);
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
        float[] longMas = iCalculatePriceService.calculateMA(candleStick, longMa);
        float[] topMas = iCalculatePriceService.calculateMA(candleStick, topMa);

        BigDecimal shortMaValue = new BigDecimal(shortMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal longMaValue = new BigDecimal(longMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal topMaValue = new BigDecimal(topMas[MovingAverageIndexEnum.NOW.code]);

        //上根21日均线大于上根60日均线
        //boolean judge1 = longMaValue.compareTo(topMaValue) > 0;

        //判断上根K线收盘价大于上根21日均线
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        //MyCandleEntry lastCandleEntry = candleEntries.get(CandlerStickIndexEnum.LAST.code);
        boolean judge2 = new BigDecimal(nowCandleEntry.getClose()).compareTo(longMaValue) > 0;

        Boolean[] buySlope1 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.FIVE_MINUTES);
        Boolean[] buySlope2 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.FIFTEEN_MINUTES);
        Boolean[] buySlope3 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.ONE_MINUTE);

        boolean result = judge2 && buySlope1[1] && buySlope2[1] && buySlope3[1] && buySlope3[2];

        if (result) {
            JSONObject candleStick2 = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                    quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIFTEEN_MINUTES, null, null, 480);
            List<MyCandleEntry> candleEntries2 = getCandlerStick(candleStick2, quantBotDetailDTO);
            BigDecimal stopLossPrice = getLowestPrice(candleEntries2, candleEntries2.size() - 1, 6);
            BigDecimal initStopLossPrice = getLowestPrice(candleEntries, candleEntries.size() - 1, 2);

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();

            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(stopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossRate((pinBarCandlerStickDetailDTO.getStopLossPrice().subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            pinBarCandlerStickDetailDTO.setStopWinRate(new BigDecimal("0.0045"));
            pinBarCandlerStickDetailDTO.setBreakEvenRate(new BigDecimal("0.001"));
            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        return result;
    }

    public Boolean judgeBuy2(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, MovingAveragePeriodEnum topMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        float[] shortMas = iCalculatePriceService.calculateMA(candleStick, shortMa);
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
        float[] longMas = iCalculatePriceService.calculateMA(candleStick, longMa);
        float[] topMas = iCalculatePriceService.calculateMA(candleStick, topMa);

        BigDecimal shortMaValue = new BigDecimal(shortMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal longMaValue = new BigDecimal(longMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal topMaValue = new BigDecimal(topMas[MovingAverageIndexEnum.NOW.code]);

        //上根21日均线大于上根60日均线
        //boolean judge1 = longMaValue.compareTo(topMaValue) > 0;

        //判断上根K线收盘价大于上根21日均线
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        //MyCandleEntry lastCandleEntry = candleEntries.get(CandlerStickIndexEnum.LAST.code);
        boolean judge2 = new BigDecimal(nowCandleEntry.getClose()).compareTo(longMaValue) > 0;

        Boolean[] buySlope1 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.FIVE_MINUTES);
        Boolean[] buySlope2 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.FIFTEEN_MINUTES);
        Boolean[] buySlope3 = judgeBuySlope(quantBotDetailDTO, CandlestickInterval.ONE_MINUTE);

        boolean result = judge2 && buySlope1[3] && buySlope2[3] && buySlope3[3] && buySlope3[2];

        if (result) {
            JSONObject candleStick2 = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                    quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIFTEEN_MINUTES, null, null, 480);
            List<MyCandleEntry> candleEntries2 = getCandlerStick(candleStick2, quantBotDetailDTO);
            BigDecimal stopLossPrice = getLowestPrice(candleEntries2, candleEntries2.size() - 1, 6);
            BigDecimal initStopLossPrice = getLowestPrice(candleEntries, candleEntries.size() - 1, 16);

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();

            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(stopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossRate((pinBarCandlerStickDetailDTO.getStopLossPrice().subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            pinBarCandlerStickDetailDTO.setStopWinRate(new BigDecimal("0.0045"));
            pinBarCandlerStickDetailDTO.setBreakEvenRate(new BigDecimal("0.001"));
            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        return result;
    }

    public Boolean judgeSell1(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, MovingAveragePeriodEnum topMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        float[] shortMas = iCalculatePriceService.calculateMA(candleStick, shortMa);
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
        float[] longMas = iCalculatePriceService.calculateMA(candleStick, longMa);
        float[] topMas = iCalculatePriceService.calculateMA(candleStick, topMa);

        BigDecimal shortMaValue = new BigDecimal(shortMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal longMaValue = new BigDecimal(longMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal topMaValue = new BigDecimal(topMas[MovingAverageIndexEnum.NOW.code]);

        //上根21日均线小于上根60日均线
        //boolean judge1 = longMaValue.compareTo(topMaValue) < 0;

        //判断上根K线收盘价小于上根21日均线
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        //MyCandleEntry lastCandleEntry = candleEntries.get(CandlerStickIndexEnum.LAST.code);
        boolean judge2 = new BigDecimal(nowCandleEntry.getClose()).compareTo(longMaValue) < 0;

        Boolean[] sellSlope1 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.FIVE_MINUTES);
        Boolean[] sellSlope2 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.FIFTEEN_MINUTES);
        Boolean[] sellSlope3 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.ONE_MINUTE);

        boolean result = judge2 && sellSlope1[1] && sellSlope2[1] && sellSlope3[1] && sellSlope3[2];

        if (result) {
            JSONObject candleStick2 = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                    quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIFTEEN_MINUTES, null, null, 480);
            List<MyCandleEntry> candleEntries2 = getCandlerStick(candleStick2, quantBotDetailDTO);
            BigDecimal stopLossPrice = getHighestPrice(candleEntries2, candleEntries2.size() - 1, 6);
            BigDecimal initStopLossPrice = getHighestPrice(candleEntries, candleEntries.size() - 1, 2);

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(stopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossRate((pinBarCandlerStickDetailDTO.getStopLossPrice().subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            pinBarCandlerStickDetailDTO.setStopWinRate(new BigDecimal("0.0045"));
            pinBarCandlerStickDetailDTO.setBreakEvenRate(new BigDecimal("0.001"));
            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        return result;
    }

    public Boolean judgeSell2(JSONObject candleStick, MovingAveragePeriodEnum shortMa, MovingAveragePeriodEnum midMa, MovingAveragePeriodEnum longMa, MovingAveragePeriodEnum topMa, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        float[] shortMas = iCalculatePriceService.calculateMA(candleStick, shortMa);
        float[] midMas = iCalculatePriceService.calculateMA(candleStick, midMa);
        float[] longMas = iCalculatePriceService.calculateMA(candleStick, longMa);
        float[] topMas = iCalculatePriceService.calculateMA(candleStick, topMa);

        BigDecimal shortMaValue = new BigDecimal(shortMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal midMaValue = new BigDecimal(midMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal longMaValue = new BigDecimal(longMas[MovingAverageIndexEnum.NOW.code]);
        BigDecimal topMaValue = new BigDecimal(topMas[MovingAverageIndexEnum.NOW.code]);

        //上根21日均线小于上根60日均线
        //boolean judge1 = longMaValue.compareTo(topMaValue) < 0;

        //判断上根K线收盘价小于上根21日均线
        List<MyCandleEntry> candleEntries = getCandlerStick(candleStick, quantBotDetailDTO);
        MyCandleEntry nowCandleEntry = candleEntries.get(candleEntries.size() - 1);
        //MyCandleEntry lastCandleEntry = candleEntries.get(CandlerStickIndexEnum.LAST.code);
        boolean judge2 = new BigDecimal(nowCandleEntry.getClose()).compareTo(longMaValue) < 0;

        Boolean[] sellSlope1 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.FIVE_MINUTES);
        Boolean[] sellSlope2 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.FIFTEEN_MINUTES);
        Boolean[] sellSlope3 = judgeSellSlope(quantBotDetailDTO, CandlestickInterval.ONE_MINUTE);

        boolean result = judge2 && sellSlope1[3] && sellSlope2[3] && sellSlope3[3] && sellSlope3[2];

        if (result) {
            JSONObject candleStick2 = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                    quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), CandlestickInterval.FIFTEEN_MINUTES, null, null, 480);
            List<MyCandleEntry> candleEntries2 = getCandlerStick(candleStick2, quantBotDetailDTO);
            BigDecimal stopLossPrice = getHighestPrice(candleEntries2, candleEntries2.size() - 1, 6);
            BigDecimal initStopLossPrice = getHighestPrice(candleEntries, candleEntries.size() - 1, 16);

            PinBarCandlerStickDetailDTO pinBarCandlerStickDetailDTO = new PinBarCandlerStickDetailDTO();
            pinBarCandlerStickDetailDTO.setInitStopLossPrice(initStopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossPrice(stopLossPrice);
            pinBarCandlerStickDetailDTO.setStopLossRate((pinBarCandlerStickDetailDTO.getStopLossPrice().subtract(new BigDecimal(nowCandleEntry.getClose()))).divide(new BigDecimal(nowCandleEntry.getClose()), 6, BigDecimal.ROUND_DOWN));
            pinBarCandlerStickDetailDTO.setStopWinRate(new BigDecimal("0.0045"));
            pinBarCandlerStickDetailDTO.setBreakEvenRate(new BigDecimal("0.001"));
            pinBarCandlerStickDetailDTO.setStopWinPrice(new BigDecimal(nowCandleEntry.getClose()).multiply(BigDecimal.ONE.add(pinBarCandlerStickDetailDTO.getStopWinRate())));

            quantBotDetailDTO.setPinBarCandlerStickDetailDTO(pinBarCandlerStickDetailDTO);
            //更新交易对详情
            String userBotKey = KeyContactUtil.getUserBotKey(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getDirection(), Integer.valueOf(quantBotDetailDTO.getLeverRate()), quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), quantBotDetailDTO.getUserId());
            stringRedisTemplate.opsForValue().set(userBotKey, JSON.toJSONString(quantBotDetailDTO));
        }

        return result;
    }

    //---------------------------------------------------ATR-------------------------------------------------

    /**
     * 获取今日浮动盈亏
     *
     * @return
     */
    public BigDecimal getTodayFloatProfit(QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        BigDecimal todayFloatProfit = BigDecimal.ZERO;
        ProfitAndFeeDetail reqDTO = new ProfitAndFeeDetail();
        reqDTO.setUserId(quantBotDetailDTO.getUserId());
        reqDTO.setExchangeType(Integer.valueOf(quantBotDetailDTO.getExchangeType()));
        List<ProfitAndFeeDetail> profitAndFeeDetails = profitAndFeeDetailMapperExt.selectByProfitAndFeeDetail(reqDTO);
        for (ProfitAndFeeDetail profitAndFeeDetail : profitAndFeeDetails) {
            todayFloatProfit = todayFloatProfit.add(profitAndFeeDetail.getTodayRealizedAmount());
        }

        List<UserBot> userBots = userBotMapperExt.selectBotsByUserId(Integer.valueOf(UserBotStatusTypeEnum.ACTIVE.getCode()), quantBotDetailDTO.getUserId(), Integer.valueOf(quantBotDetailDTO.getExchangeType()));

        for (int i = 0; i < userBots.size(); i++) {
            UserBot value = userBots.get(i);
            String userBotKey = KeyContactUtil.getUserBotKey(value.getExchangeType(), value.getDirection(), value.getLeverRate(), value.getDestinationCoin(),
                    value.getSourceCoin(), value.getUserId());

            QuantBotDetailDTO activeUserDetail = JSONObject.parseObject(stringRedisTemplate.opsForValue().get(userBotKey), QuantBotDetailDTO.class);

            //用机器人中的卖盘涨幅作为涨幅
            BigDecimal currentRate = new BigDecimal(activeUserDetail.getAskRise());

            //已开启
            if (quantBotDetailDTO.getStatus().equals(UserBotStatusTypeEnum.ACTIVE.getCode())) {
                BigDecimal floatProfit = new BigDecimal(activeUserDetail.getAvgPrice()).multiply(new BigDecimal(activeUserDetail.getPositionNum())).multiply(currentRate).setScale(8, BigDecimal.ROUND_DOWN);
                todayFloatProfit = todayFloatProfit.add(floatProfit);
            }
        }

        return todayFloatProfit;
    }

    /**
     * 获取今日已实现盈亏
     *
     * @return
     */
    public BigDecimal getTodayRealizedProfit(QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        UserWalletInfo userWalletInfo = new UserWalletInfo();
        userWalletInfo.setUserId(quantBotDetailDTO.getUserId());
        UserWalletInfo result = userWalletInfoMapperExt.selectOne(userWalletInfo);
        BigDecimal todayRealizedProfit = result.getTodayProfit();
        return todayRealizedProfit;
    }

    private Boolean[] judgeBuySlope(QuantBotDetailDTO quantBotDetailDTO, CandlestickInterval period) throws Exception {
        //大周期定方向,上根5日均线和13日均线大于上根21日均线，上根K收盘价大于上根21日均线
        JSONObject bigCandleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), period, null, null, 480);
        List<MyCandleEntry> bigCandleEntries = getCandlerStick(bigCandleStick, quantBotDetailDTO);
        MyCandleEntry lastBigCandleEntry = bigCandleEntries.get(bigCandleEntries.size() - 1);
        float[] bigMas5 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA5);
        BigDecimal bigMaValue5Last = new BigDecimal(bigMas5[MovingAverageIndexEnum.NOW.code]);
        float[] bigMas13 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA13);
        BigDecimal bigMaValue13Last = new BigDecimal(bigMas13[MovingAverageIndexEnum.NOW.code]);
        float[] bigMas21 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA21);
        BigDecimal bigMaValue21Last = new BigDecimal(bigMas21[MovingAverageIndexEnum.NOW.code]);
        float[] bigMas60 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA60);
        BigDecimal bigMaValue60Last = new BigDecimal(bigMas60[MovingAverageIndexEnum.NOW.code]);
        Boolean direction = (bigMaValue5Last.compareTo(bigMaValue21Last) > 0) &&
                (bigMaValue13Last.compareTo(bigMaValue21Last) > 0) &&
                (new BigDecimal(lastBigCandleEntry.getClose()).compareTo(bigMaValue21Last) > 0);

        BigDecimal smallMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas5[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas5[MovingAverageIndexEnum.LAST.code]));
        BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas13[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas13[MovingAverageIndexEnum.LAST.code]));
        BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas21[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas21[MovingAverageIndexEnum.LAST.code]));
        BigDecimal topMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas60[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas60[MovingAverageIndexEnum.LAST.code]));
        Boolean judgeSlopeRatio = (smallMaDegree.compareTo(BigDecimal.ZERO) > 0) && (midMaDegree.compareTo(BigDecimal.ZERO) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0) && (topMaDegree.compareTo(BigDecimal.ZERO) > 0);

        Boolean direction1 = (bigMaValue5Last.compareTo(bigMaValue13Last) > 0) && (bigMaValue5Last.compareTo(bigMaValue21Last) > 0) && (bigMaValue13Last.compareTo(bigMaValue60Last) > 0);

        Boolean judgeSlopeRatio1 = (smallMaDegree.compareTo(BigDecimal.ZERO) > 0) && (midMaDegree.compareTo(BigDecimal.ZERO) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0);
        Boolean judgeSlopeRatio2 = (smallMaDegree.compareTo(BigDecimal.ZERO) > 0) && (midMaDegree.compareTo(BigDecimal.ZERO) > 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) > 0) && (topMaDegree.compareTo(BigDecimal.ZERO) <= 0);

        Boolean[] result = {direction, judgeSlopeRatio, direction1, judgeSlopeRatio1, judgeSlopeRatio2};

        return result;
    }

    private Boolean[] judgeSellSlope(QuantBotDetailDTO quantBotDetailDTO, CandlestickInterval period) throws Exception {
        //大周期定方向,上根5日均线和13日均线小于上根21日均线，上根K收盘价小于上根21日均线
        JSONObject bigCandleStick = feignService.getCandleStick(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin(), period, null, null, 480);
        List<MyCandleEntry> bigCandleEntries = getCandlerStick(bigCandleStick, quantBotDetailDTO);
        MyCandleEntry lastBigCandleEntry = bigCandleEntries.get(bigCandleEntries.size() - 1);
        float[] bigMas5 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA5);
        BigDecimal bigMaValue5Last = new BigDecimal(bigMas5[MovingAverageIndexEnum.NOW.code]);
        float[] bigMas13 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA13);
        BigDecimal bigMaValue13Last = new BigDecimal(bigMas13[MovingAverageIndexEnum.NOW.code]);
        float[] bigMas21 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA21);
        BigDecimal bigMaValue21Last = new BigDecimal(bigMas21[MovingAverageIndexEnum.NOW.code]);
        float[] bigMas60 = iCalculatePriceService.calculateMA(bigCandleStick, MovingAveragePeriodEnum.MA60);
        BigDecimal bigMaValue60Last = new BigDecimal(bigMas60[MovingAverageIndexEnum.NOW.code]);
        boolean direction = (bigMaValue5Last.compareTo(bigMaValue21Last) < 0) &&
                (bigMaValue13Last.compareTo(bigMaValue21Last) < 0) &&
                (new BigDecimal(lastBigCandleEntry.getClose()).compareTo(bigMaValue21Last) < 0);

        BigDecimal smallMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas5[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas5[MovingAverageIndexEnum.LAST.code]));
        BigDecimal midMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas13[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas13[MovingAverageIndexEnum.LAST.code]));
        BigDecimal bigMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas21[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas21[MovingAverageIndexEnum.LAST.code]));
        BigDecimal topMaDegree = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(bigMas60[MovingAverageIndexEnum.NOW.code]), new BigDecimal(bigMas60[MovingAverageIndexEnum.LAST.code]));
        Boolean judgeSlopeRatio = (smallMaDegree.compareTo(BigDecimal.ZERO) < 0) && (midMaDegree.compareTo(BigDecimal.ZERO) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0) && (topMaDegree.compareTo(BigDecimal.ZERO) < 0);

        Boolean direction1 = (bigMaValue5Last.compareTo(bigMaValue13Last) < 0) && (bigMaValue5Last.compareTo(bigMaValue21Last) < 0) && (bigMaValue13Last.compareTo(bigMaValue60Last) < 0);

        Boolean judgeSlopeRatio1 = (smallMaDegree.compareTo(BigDecimal.ZERO) < 0) && (midMaDegree.compareTo(BigDecimal.ZERO) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0);
        Boolean judgeSlopeRatio2 = (smallMaDegree.compareTo(BigDecimal.ZERO) < 0) && (midMaDegree.compareTo(BigDecimal.ZERO) < 0) && (bigMaDegree.compareTo(BigDecimal.ZERO) < 0) && (topMaDegree.compareTo(BigDecimal.ZERO) >= 0);

        Boolean[] result = {direction, judgeSlopeRatio, direction1, judgeSlopeRatio1, judgeSlopeRatio2};

        return result;
    }

    private Boolean getBuySlopeRatio(JSONObject candleStick, Boolean judgeMas1, Boolean judgeLastMas) throws Exception {
        //float[] mas1 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA1);
        float[] mas5 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA5);
        float[] mas13 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA13);
        float[] mas21 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA21);
        /*float[] mas29 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA29);
        float[] mas37 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA37);
        float[] mas45 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA45);
        float[] mas53 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA53);*/
        //float[] mas60 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA60);

        //BigDecimal ma1DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas1[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas1[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma5DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas5[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas5[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma13DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas13[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas13[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma21DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas21[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas21[MovingAverageIndexEnum.LAST.code]));
        /*BigDecimal ma29DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas29[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas29[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma37DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas37[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas37[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma45DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas45[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas45[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma53DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas53[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas53[MovingAverageIndexEnum.LAST.code]));*/
        //BigDecimal ma60DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas60[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas60[MovingAverageIndexEnum.LAST.code]));
        Boolean judgeSlopeRatioNow = /*(judgeMas1 ? ma1DegreeNow.compareTo(BigDecimal.ZERO) > 0 : true) &&*/
                (ma5DegreeNow.compareTo(BigDecimal.ZERO) > 0) &&
                        (ma13DegreeNow.compareTo(BigDecimal.ZERO) > 0) &&
                        (ma21DegreeNow.compareTo(BigDecimal.ZERO) > 0)/*&&
                (ma29DegreeNow.compareTo(BigDecimal.ZERO) > 0) &&
                (ma37DegreeNow.compareTo(BigDecimal.ZERO) > 0) &&
                (ma45DegreeNow.compareTo(BigDecimal.ZERO) > 0) &&
                (ma53DegreeNow.compareTo(BigDecimal.ZERO) > 0) &&
                        (ma60DegreeNow.compareTo(BigDecimal.ZERO) > 0)*/;

        //BigDecimal ma1DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas1[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas1[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal ma5DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas5[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas5[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal ma13DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas13[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas13[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal ma21DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas21[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas21[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma29DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas29[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas29[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma37DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas37[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas37[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma45DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas45[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas45[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma53DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas53[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas53[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma60DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas60[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas60[MovingAverageIndexEnum.LAST2.code]));
        Boolean judgeSlopeRatioLast = /*(judgeMas1 ? ma1DegreeLast.compareTo(BigDecimal.ZERO) > 0 : true) &&*/
                (ma5DegreeLast.compareTo(BigDecimal.ZERO) > 0) &&
                        (ma13DegreeLast.compareTo(BigDecimal.ZERO) > 0) &&
                        (ma21DegreeLast.compareTo(BigDecimal.ZERO) > 0)/*&&
                (ma29DegreeLast.compareTo(BigDecimal.ZERO) > 0) &&
                (ma37DegreeLast.compareTo(BigDecimal.ZERO) > 0) &&
                (ma45DegreeLast.compareTo(BigDecimal.ZERO) > 0) &&
                (ma53DegreeLast.compareTo(BigDecimal.ZERO) > 0) &&
                        (ma60DegreeLast.compareTo(BigDecimal.ZERO) > 0)*/;

        judgeSlopeRatioLast = judgeLastMas ? judgeSlopeRatioLast : true;

        Boolean open = judgeSlopeRatioNow && judgeSlopeRatioLast;

        return open;
    }

    private Boolean getBuyCompareValue(JSONObject candleStick) throws Exception {
        float[] mas1 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA1);
        float[] mas5 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA5);
        float[] mas13 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA13);
        float[] mas21 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA21);
        float[] mas29 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA29);
        float[] mas37 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA37);
        /*float[] mas45 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA45);
        float[] mas53 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA53);
        float[] mas60 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA60);*/

        BigDecimal ma1Value = new BigDecimal(mas1[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma5Value = new BigDecimal(mas5[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma13Value = new BigDecimal(mas13[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma21Value = new BigDecimal(mas21[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma29Value = new BigDecimal(mas29[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma37Value = new BigDecimal(mas37[MovingAverageIndexEnum.NOW.code]);
       /* BigDecimal ma45Value = new BigDecimal(mas45[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma53Value = new BigDecimal(mas53[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma60Value = new BigDecimal(mas60[MovingAverageIndexEnum.NOW.code]);*/

        Boolean compareMaValue = (ma1Value.compareTo(ma5Value) > 0) &&
                (ma5Value.compareTo(ma13Value) > 0) &&
                (ma13Value.compareTo(ma21Value) > 0) &&
                (ma21Value.compareTo(ma29Value) > 0) &&
                (ma29Value.compareTo(ma37Value) > 0) /*&&
                (ma37Value.compareTo(ma45Value) > 0) &&
                (ma45Value.compareTo(ma53Value) > 0) &&
                (ma53Value.compareTo(ma60Value) > 0)*/;

        return compareMaValue;
    }

    private Boolean getSellSlopeRatio(JSONObject candleStick, Boolean judgeMas1, Boolean judgeLastMas) throws Exception {
        //float[] mas1 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA1);
        float[] mas5 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA5);
        float[] mas13 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA13);
        float[] mas21 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA21);
        /*float[] mas29 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA29);
        float[] mas37 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA37);
        float[] mas45 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA45);
        float[] mas53 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA53);*/
        //float[] mas60 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA60);

        //BigDecimal ma1DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas1[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas1[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma5DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas5[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas5[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma13DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas13[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas13[MovingAverageIndexEnum.LAST.code]));
        BigDecimal ma21DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas21[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas21[MovingAverageIndexEnum.LAST.code]));
        //BigDecimal ma29DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas29[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas29[MovingAverageIndexEnum.LAST.code]));
        //BigDecimal ma37DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas37[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas37[MovingAverageIndexEnum.LAST.code]));
        //BigDecimal ma45DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas45[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas45[MovingAverageIndexEnum.LAST.code]));
        //BigDecimal ma53DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas53[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas53[MovingAverageIndexEnum.LAST.code]));
        //BigDecimal ma60DegreeNow = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas60[MovingAverageIndexEnum.NOW.code]), new BigDecimal(mas60[MovingAverageIndexEnum.LAST.code]));
        Boolean judgeSlopeRatioNow = /*(judgeMas1 ? ma1DegreeNow.compareTo(BigDecimal.ZERO) < 0 : true) &&*/
                (ma5DegreeNow.compareTo(BigDecimal.ZERO) < 0) &&
                        (ma13DegreeNow.compareTo(BigDecimal.ZERO) < 0) &&
                        (ma21DegreeNow.compareTo(BigDecimal.ZERO) < 0)/* &&
                (ma29DegreeNow.compareTo(BigDecimal.ZERO) < 0) &&
                (ma37DegreeNow.compareTo(BigDecimal.ZERO) < 0) &&
                (ma45DegreeNow.compareTo(BigDecimal.ZERO) < 0) &&
                (ma53DegreeNow.compareTo(BigDecimal.ZERO) < 0) &&
                        (ma60DegreeNow.compareTo(BigDecimal.ZERO) < 0)*/;

        //BigDecimal ma1DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas1[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas1[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal ma5DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas5[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas5[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal ma13DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas13[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas13[MovingAverageIndexEnum.LAST2.code]));
        BigDecimal ma21DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas21[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas21[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma29DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas29[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas29[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma37DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas37[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas37[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma45DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas45[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas45[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma53DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas53[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas53[MovingAverageIndexEnum.LAST2.code]));
        //BigDecimal ma60DegreeLast = FinanceIndicatorsUtil.getMaDegree(new BigDecimal(mas60[MovingAverageIndexEnum.LAST.code]), new BigDecimal(mas60[MovingAverageIndexEnum.LAST2.code]));
        Boolean judgeSlopeRatioLast = /*(judgeMas1 ? ma1DegreeLast.compareTo(BigDecimal.ZERO) < 0 : true) &&*/
                (ma5DegreeLast.compareTo(BigDecimal.ZERO) < 0) &&
                        (ma13DegreeLast.compareTo(BigDecimal.ZERO) < 0) &&
                        (ma21DegreeLast.compareTo(BigDecimal.ZERO) < 0)/* &&
                (ma29DegreeLast.compareTo(BigDecimal.ZERO) < 0) &&
                (ma37DegreeLast.compareTo(BigDecimal.ZERO) < 0) &&
                (ma45DegreeLast.compareTo(BigDecimal.ZERO) < 0) &&
                (ma53DegreeLast.compareTo(BigDecimal.ZERO) < 0) &&
                        (ma60DegreeLast.compareTo(BigDecimal.ZERO) < 0)*/;

        judgeSlopeRatioLast = judgeLastMas ? judgeSlopeRatioLast : true;

        Boolean open = judgeSlopeRatioNow && judgeSlopeRatioLast;

        return open;
    }

    private Boolean getSellCompareValue(JSONObject candleStick) throws Exception {
        float[] mas1 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA1);
        float[] mas5 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA5);
        float[] mas13 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA13);
        float[] mas21 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA21);
        float[] mas29 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA29);
        float[] mas37 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA37);
       /* float[] mas45 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA45);
        float[] mas53 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA53);
        float[] mas60 = iCalculatePriceService.calculateMA(candleStick, MovingAveragePeriodEnum.MA60);*/

        BigDecimal ma1Value = new BigDecimal(mas1[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma5Value = new BigDecimal(mas5[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma13Value = new BigDecimal(mas13[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma21Value = new BigDecimal(mas21[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma29Value = new BigDecimal(mas29[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma37Value = new BigDecimal(mas37[MovingAverageIndexEnum.NOW.code]);
        /*BigDecimal ma45Value = new BigDecimal(mas45[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma53Value = new BigDecimal(mas53[MovingAverageIndexEnum.NOW.code]);
        BigDecimal ma60Value = new BigDecimal(mas60[MovingAverageIndexEnum.NOW.code]);*/

        Boolean compareMaValue = (ma1Value.compareTo(ma5Value) < 0) &&
                (ma5Value.compareTo(ma13Value) < 0) &&
                (ma13Value.compareTo(ma21Value) < 0) &&
                (ma21Value.compareTo(ma29Value) < 0) &&
                (ma29Value.compareTo(ma37Value) < 0) /*&&
                (ma37Value.compareTo(ma45Value) < 0) &&
                (ma45Value.compareTo(ma53Value) < 0) &&
                (ma53Value.compareTo(ma60Value) < 0)*/;

        return compareMaValue;
    }

    /**
     * 计算rsi值
     *
     * @return
     */
    public BigDecimal getRsi(BarSeries barSeries, int rsiTimeFrame, int index) {
        // 创建RSI指标对象
        RSIIndicator rsiIndicator = new RSIIndicator(new ClosePriceIndicator(barSeries), rsiTimeFrame);
        // 获取RSI值
        Num rsiValue = rsiIndicator.getValue(index);
        BigDecimal value = new BigDecimal(rsiValue.doubleValue());
        return value;
    }

    /**
     * 判断是否底背离
     *
     * @return
     */
    public Boolean judgeBottomDivergence(BarSeries barSeries, int shortPeriod, int longPeriod, int signalPeriod) {
        List<Num> macDhistogram = getMACDhistogram(barSeries, shortPeriod, longPeriod, signalPeriod);
        List<Num> macDvalue = getMACDvalue(barSeries, shortPeriod, longPeriod);
        List<Bar> barData = barSeries.getBarData();
        Bar last2Bar = barData.get(barData.size() - 3);
        barData = barData.subList(barData.size() - macDhistogram.size(), barData.size());

        int lastIndex = macDhistogram.size() - 1;
        double lastHistogram = macDhistogram.get(lastIndex).doubleValue();
        if (lastHistogram > 0) {
            return false;
        }

        List<Double> filteredData = new ArrayList<>();
        List<Bar> filteredPrices = new ArrayList<>();
        List<Double> filteredMacds = new ArrayList<>();

        for (int i = lastIndex; i >= 0; i--) {
            double histogram = macDhistogram.get(i).doubleValue();
            Bar bar = barData.get(i);
            Num num = macDvalue.get(i);
            if (histogram < 0) {
                filteredData.add(histogram);
                filteredPrices.add(bar);
                filteredMacds.add(num.doubleValue());
            } else {
                break;
            }
        }

        if (filteredData.size() >= 8) {
            List<Double> valleys = new ArrayList<>();
            List<Double> valleyPrices = new ArrayList<>();
            List<Bar> valleyBars = new ArrayList<>();
            List<Double> valleyMacds = new ArrayList<>();

            // 筛选谷值
            for (int i = 2; i < filteredData.size() - 1; i++) {
                double current = filteredData.get(i);
                double prev = filteredData.get(i - 1);
                double next = filteredData.get(i + 1);
                Bar bar = filteredPrices.get(i);
                Double macd = filteredMacds.get(i);

                if (current < prev && current < next) {
                    valleys.add(current);
                    valleyPrices.add(bar.getLowPrice().doubleValue());
                    valleyBars.add(bar);
                    valleyMacds.add(macd);
                }

                if (valleys.size() >= 3) {
                    break;
                }
            }

            for (Double valleyMacd : valleyMacds) {
                if (valleyMacd >= 0) {
                    return false;
                }
            }

            Collections.reverse(valleys);
            Collections.reverse(valleyPrices);
            Collections.reverse(valleyBars);

            if (valleys.size() >= 3 && isIncreasing(valleys) && isDecreasing(valleyPrices)) {
                System.out.println("Bottom Divergence Detected");
                ZonedDateTime currentValleyBeginTime = valleyBars.get(valleyBars.size() - 1).getBeginTime();
                ZonedDateTime currentValleyEndTime = valleyBars.get(valleyBars.size() - 1).getEndTime();

                ZonedDateTime last2BarBeginTime = last2Bar.getBeginTime();
                ZonedDateTime last2BarEndTime = last2Bar.getEndTime();

                if (!currentValleyBeginTime.equals(last2BarBeginTime) || !currentValleyEndTime.equals(last2BarEndTime)) {
                    return false;
                } else {
                    return true;
                }
            } else {
                System.out.println("No Divergence Detected");
                return false;
            }
        } else {
            System.out.println("Insufficient data to detect divergences");
            return false;
        }
    }

    /**
     * 判断是否顶背离
     *
     * @return
     */
    public Boolean judgeTopDivergence(BarSeries barSeries, int shortPeriod, int longPeriod, int signalPeriod) {
        List<Num> macDhistogram = getMACDhistogram(barSeries, shortPeriod, longPeriod, signalPeriod);
        List<Num> macDvalue = getMACDvalue(barSeries, shortPeriod, longPeriod);
        List<Bar> barData = barSeries.getBarData();
        Bar last2Bar = barData.get(barData.size() - 3);
        barData = barData.subList(barData.size() - macDhistogram.size(), barData.size());

        int lastIndex = macDhistogram.size() - 1;
        double lastHistogram = macDhistogram.get(lastIndex).doubleValue();
        if (lastHistogram < 0) {
            return false;
        }

        List<Double> filteredData = new ArrayList<>();
        List<Bar> filteredPrices = new ArrayList<>();
        List<Double> filteredMacds = new ArrayList<>();

        for (int i = lastIndex; i >= 0; i--) {
            double histogram = macDhistogram.get(i).doubleValue();
            Bar bar = barData.get(i);
            Num num = macDvalue.get(i);
            if (histogram > 0) {
                filteredData.add(histogram);
                filteredPrices.add(bar);
                filteredMacds.add(num.doubleValue());
            } else {
                break;
            }
        }

        if (filteredData.size() >= 8) {
            List<Double> peaks = new ArrayList<>();
            List<Double> peakPrices = new ArrayList<>();
            List<Bar> peakBars = new ArrayList<>();
            List<Double> peakMacds = new ArrayList<>();

            // 筛选峰值
            for (int i = 2; i < filteredData.size() - 1; i++) {
                double current = filteredData.get(i);
                double prev = filteredData.get(i - 1);
                double next = filteredData.get(i + 1);
                Bar bar = filteredPrices.get(i);
                Double macd = filteredMacds.get(i);

                if (current > prev && current > next) {
                    peaks.add(current);
                    peakPrices.add(bar.getHighPrice().doubleValue());
                    peakBars.add(bar);
                    peakMacds.add(macd);
                }

                if (peaks.size() >= 3) {
                    break;
                }
            }

            for (Double peakMacd : peakMacds) {
                if (peakMacd <= 0) {
                    return false;
                }
            }

            Collections.reverse(peaks);
            Collections.reverse(peakPrices);
            Collections.reverse(peakBars);

            if (peaks.size() >= 3 && isDecreasing(peaks) && isIncreasing(peakPrices)) {
                System.out.println("Top Divergence Detected");
                ZonedDateTime currentPeakBeginTime = peakBars.get(peakBars.size() - 1).getBeginTime();
                ZonedDateTime currentPeakEndTime = peakBars.get(peakBars.size() - 1).getEndTime();

                ZonedDateTime last2BarBeginTime = last2Bar.getBeginTime();
                ZonedDateTime last2BarEndTime = last2Bar.getEndTime();

                if (!currentPeakBeginTime.equals(last2BarBeginTime) || !currentPeakEndTime.equals(last2BarEndTime)) {
                    return false;
                } else {
                    return true;
                }
            } else {
                System.out.println("No Divergence Detected");
                return false;
            }
        } else {
            System.out.println("Insufficient data to detect divergences");
            return false;
        }
    }

    /**
     * 计算RSRS斜率的标准分
     *
     * @return
     */
    public double calculateStandardScore(double rsrsSlope, List<Double> slopeList) {
        double mean = calculateMean(slopeList);
        double stdDeviation = calculateStandardDeviation(slopeList);
        return (rsrsSlope - mean) / stdDeviation;
    }

    // 计算均值
    private double calculateMean(List<Double> values) {
        double sum = 0.0;
        for (Double value : values) {
            sum += value;
        }
        return sum / values.size();
    }

    // 计算标准差
    private double calculateStandardDeviation(List<Double> values) {
        double mean = calculateMean(values);
        double sum = 0.0;
        for (Double value : values) {
            sum += Math.pow(value - mean, 2);
        }
        double variance = sum / (values.size() - 1);
        return Math.sqrt(variance);
    }

    public BarSeries getBarSeries(List<MyCandleEntry> candleEntries, Duration timePeriod) {
        // 创建一个时间序列
        BarSeries series = new BaseBarSeries();

        // 添加价格数据到时间序列
        for (MyCandleEntry myCandleEntry : candleEntries) {
            series.addBar(new BaseBar(timePeriod, ZonedDateTime.ofInstant(Instant.ofEpochMilli(myCandleEntry.getCloseTime()), ZoneId.systemDefault()),
                    PrecisionNum.valueOf(myCandleEntry.getOpen()),
                    PrecisionNum.valueOf(myCandleEntry.getHigh()),
                    PrecisionNum.valueOf(myCandleEntry.getLow()),
                    PrecisionNum.valueOf(myCandleEntry.getClose()),
                    PrecisionNum.valueOf(myCandleEntry.getVolume()),
                    PrecisionNum.valueOf(myCandleEntry.getQuoteAssetVolume()))
            );
        }

        return series;
    }

    public List<Num> getMACDvalue(BarSeries barSeries, int shortPeriod, int longPeriod) {
        // 计算MACD指标
        MACDIndicator macdIndicator = new MACDIndicator(new ClosePriceIndicator(barSeries), shortPeriod, longPeriod);

        List<Num> macdValues = new ArrayList<>();
        // 访问MACD指标的数值
        for (int i = 0; i < barSeries.getBarCount(); i++) {
            Num macdValue = macdIndicator.getValue(i);
            macdValues.add(macdValue);
        }

        return macdValues;
    }

    public List<Num>[] getMACD_signal_value(BarSeries barSeries, int shortPeriod, int longPeriod, int signalPeriod) {
        MACDIndicator macdIndicator = new MACDIndicator(new ClosePriceIndicator(barSeries), shortPeriod, longPeriod);
        Indicator<Num> macdLine = macdIndicator;
        EMAIndicator signalLine = new EMAIndicator(macdLine, signalPeriod);

        List<Num> macdValues = new ArrayList<>();
        List<Num> signalValues = new ArrayList<>();
        for (int i = signalPeriod; i < barSeries.getBarCount(); i++) {
            Num macdValue = macdLine.getValue(i);
            Num signalValue = signalLine.getValue(i);

            macdValues.add(macdValue);
            signalValues.add(signalValue);
        }
        List<Num>[] results = new ArrayList[2];
        results[0] = macdValues;
        results[1] = signalValues;

        return results;
    }

    public List<Num> getMACDhistogram(BarSeries barSeries, int shortPeriod, int longPeriod, int signalPeriod) {
        // 计算MACD指标
        MACDIndicator macdIndicator = new MACDIndicator(new ClosePriceIndicator(barSeries), shortPeriod, longPeriod);
        Indicator<Num> macdLine = macdIndicator;
        EMAIndicator signalLine = new EMAIndicator(macdLine, signalPeriod);

        List<Num> histogramValues = new ArrayList<>();
        // 计算 Histogram 值
        for (int i = signalPeriod; i < barSeries.getBarCount(); i++) {
            Num macdValue = macdLine.getValue(i);
            Num signalValue = signalLine.getValue(i);

            // 计算 Histogram 值
            Num histogram = macdValue.minus(signalValue);
            histogramValues.add(histogram);
        }
        return histogramValues;
    }

    public List<Num> getATR(BarSeries barSeries, int atrPeriod) {
        // 创建 ATRIndicator 对象
        ATRIndicator atrIndicator = new ATRIndicator(barSeries, atrPeriod);

        List<Num> atrValues = new ArrayList<>();
        // 访问 ATR 指标的数值
        for (int i = atrPeriod; i < barSeries.getBarCount(); i++) {
            atrValues.add(atrIndicator.getValue(i));
        }

        return atrValues;
    }

    private static boolean isIncreasing(List<Double> data) {
        for (int i = 1; i < data.size(); i++) {
            if (data.get(i) <= data.get(i - 1)) {
                return false;
            }
        }
        return true;
    }

    private static boolean isDecreasing(List<Double> data) {
        for (int i = 1; i < data.size(); i++) {
            if (data.get(i) >= data.get(i - 1)) {
                return false;
            }
        }
        return true;
    }

    private boolean isBullEntry(List<MyCandleEntry> candleEntries, List<Num> macdValues, int signalPeriod, int judgePeriod) {
        int minMacdIndex = 0;
        BigDecimal minMacd = new BigDecimal("9999999999999999999999999999");

        for (int i = candleEntries.size() - 2; i > candleEntries.size() - 2 - judgePeriod; i--) {
            BigDecimal macd = BigDecimal.valueOf(macdValues.get(i - signalPeriod).doubleValue());
            if (macd.compareTo(minMacd) < 0) {
                minMacd = macd;
                minMacdIndex = i;
            }
        }

        int candleNum = candleEntries.size() - 1 - minMacdIndex;
        BigDecimal maxPrice = new BigDecimal("-9999999999999999999999999999");
        for (int i = minMacdIndex - 1; i > minMacdIndex - 1 - candleNum; i--) {
            BigDecimal high = BigDecimal.valueOf(candleEntries.get(i).getHigh());
            if (high.compareTo(maxPrice) > 0) {
                maxPrice = high;
            }
        }

        BigDecimal lastClose = BigDecimal.valueOf(candleEntries.get(candleEntries.size() - 2).getClose());

        return lastClose.compareTo(maxPrice) > 0;
    }

    private boolean isBearEntry(List<MyCandleEntry> candleEntries, List<Num> macdValues, int signalPeriod, int judgePeriod) {
        int maxMacdIndex = 0;
        BigDecimal maxMacd = new BigDecimal("-9999999999999999999999999999");

        for (int i = candleEntries.size() - 2; i > candleEntries.size() - 2 - judgePeriod; i--) {
            BigDecimal macd = BigDecimal.valueOf(macdValues.get(i - signalPeriod).doubleValue());
            if (macd.compareTo(maxMacd) > 0) {
                maxMacd = macd;
                maxMacdIndex = i;
            }
        }

        int candleNum = candleEntries.size() - 1 - maxMacdIndex;
        BigDecimal minPrice = new BigDecimal("9999999999999999999999999999");
        for (int i = maxMacdIndex - 1; i > maxMacdIndex - 1 - candleNum; i--) {
            BigDecimal low = BigDecimal.valueOf(candleEntries.get(i).getLow());
            if (low.compareTo(minPrice) < 0) {
                minPrice = low;
            }
        }

        BigDecimal lastClose = BigDecimal.valueOf(candleEntries.get(candleEntries.size() - 2).getClose());

        return lastClose.compareTo(minPrice) < 0;
    }

    public Num[] getStochRsi(BarSeries series, int rsiBarCount, int stockBarCount, int kPeriod, int dPeriod, int index) {
        // 创建相对强弱指数 (RSI) 指标
        RSIIndicator rsi = new RSIIndicator(new ClosePriceIndicator(series), rsiBarCount);
        // 创建 Stochastic RSI 指标
        StochasticRSIIndicator stochRsi = new StochasticRSIIndicator(rsi, stockBarCount);
        // 计算 StochRSI K 值
        SMAIndicator stochK = new SMAIndicator(stochRsi, kPeriod);
        // 计算 StochRSI D 值
        SMAIndicator stochD = new SMAIndicator(stochK, dPeriod);
        Num StochRSI_K = stochK.getValue(index).multipliedBy(series.numOf(100));
        Num StochRSI_D = stochD.getValue(index).multipliedBy(series.numOf(100));
        Num[] stoch_values = new Num[]{StochRSI_K, StochRSI_D};
        return stoch_values;
    }

    public double getADX(BarSeries series, int diBarCount, int adxBarCount, int index) {
        ADXIndicator adxIndicator = new ADXIndicator(series, diBarCount, adxBarCount);
        double adx = adxIndicator.getValue(index).doubleValue();
        return adx;
    }

    public BigDecimal[] getDepthVolume(QuantBotDetailDTO quantBotDetailDTO, BigDecimal ratioLimit) throws Exception {
        JSONObject depth = feignService.getMarketPriceDepth(Integer.valueOf(quantBotDetailDTO.getExchangeType()), quantBotDetailDTO.getUserId(),
                quantBotDetailDTO.getDestinationCoin(), quantBotDetailDTO.getSourceCoin());
        JSONArray bids = depth.getJSONArray("bids");
        JSONArray asks = depth.getJSONArray("asks");

        BigDecimal totalBidVolume = BigDecimal.ZERO;
        BigDecimal totalAskVolume = BigDecimal.ZERO;

        JSONArray firstBid = (JSONArray) (bids.get(0));
        BigDecimal firstBidPrice = new BigDecimal(String.valueOf(firstBid.get(0)));
        BigDecimal bidPriceByMaxVolume = null;
        BigDecimal bidMaxVolume = new BigDecimal(Double.MIN_VALUE);
        for (Object obj : bids) {
            JSONArray bid = (JSONArray) obj;
            BigDecimal bidPrice = new BigDecimal(String.valueOf(bid.get(0)));
            BigDecimal bidVolume = new BigDecimal(String.valueOf(bid.get(1)));
            BigDecimal ratio = firstBidPrice.subtract(bidPrice).divide(firstBidPrice, 8, BigDecimal.ROUND_DOWN).abs();
            if (ratio.compareTo(ratioLimit) <= 0) {
                totalBidVolume = totalBidVolume.add(bidVolume);
                if (bidVolume.compareTo(bidMaxVolume) > 0) {
                    bidMaxVolume = bidVolume;
                    bidPriceByMaxVolume = bidPrice;
                }
            } else {
                break;
            }
        }

        JSONArray firstAsk = (JSONArray) (asks.get(0));
        BigDecimal firstAskPrice = new BigDecimal(String.valueOf(firstAsk.get(0)));
        BigDecimal askPriceByMaxVolume = null;
        BigDecimal askMaxVolume = new BigDecimal(Double.MIN_VALUE);
        for (Object obj : asks) {
            JSONArray ask = (JSONArray) obj;
            BigDecimal askPrice = new BigDecimal(String.valueOf(ask.get(0)));
            BigDecimal askVolume = new BigDecimal(String.valueOf(ask.get(1)));
            BigDecimal ratio = firstAskPrice.subtract(askPrice).divide(firstAskPrice, 8, BigDecimal.ROUND_DOWN).abs();
            if (ratio.compareTo(ratioLimit) <= 0) {
                totalAskVolume = totalAskVolume.add(askVolume);
                if (askVolume.compareTo(askMaxVolume) > 0) {
                    askMaxVolume = askVolume;
                    askPriceByMaxVolume = askPrice;
                }
            } else {
                break;
            }
        }

        return new BigDecimal[]{totalBidVolume, totalAskVolume};
    }

}
